思路

其实这是一道非常经典的分苹果问题:
有m个一样的苹果和n个一样的盘子,把苹果放盘子里,每个盘子允许0-m个苹果,求问有多少种分法?

与本题的共通之点在于,输入的正整数可以看成m个苹果,拆分出的加数个数可以看成n个盘子,例如:4 = 1 + 1 + 3,可以看成4个苹果分到3个盘子中的一种情况。

为了更好地理解,我们继续回到分苹果问题上。
我们假设分苹果的结果由这样一个函数得出:f(m, n)

思考一种特殊情况:如果只有1个苹果,或者只有1个盘子,无论怎么折腾是不是只有1种分法?
至此我们就轻松找到了递归解法的出口,也找到了动态规划的base。
但是注意,我们这里原题是拆分整数,理论上整数可以为0,拆分的个数也可以为0,我们把这种情况也划分进去(主要是为了更方便处理动态规划的数组,后面会说),转换成代码即为:

  1. if m <= 1 or n <= 1:
  2. f(m,n) = 1;

再考虑m<n的情况,盘子比苹果多得多,那我把多余的盘子拿走也不会有任何影响:

  1. if m < n:
  2. f(m,n) = f(m, m)

再考虑最后一种情况m>=n,苹果比盘子多或者和盘子一样多,可以由2种场景涵盖:
①不存在空盘子。我先把每个盘子都放上1个苹果,就不存在空盘子啦,然后继续分我的苹果:

  1. f(m - n, n)

②存在空盘子。有空盘子存在,换种说法至少让1个盘子为空,那我先把这个空盘子拿出来,然后继续分我的苹果:

  1. f(m, n - 1)

以上2种情况转换为代码即为:

  1. if (m >= n):
  2. f(m, m) = f(m - n, n) + f(m, n - 1)

最后这种情况为啥能等效,可能要花点力气去理解。

代码

现在我们可以开始撸代码了,先上递归解法:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Scanner sc = new Scanner(System.in);
  4. while (sc.hasNext()) {
  5. int num = sc.nextInt();
  6. System.out.println(cal(num, num));
  7. }
  8. }
  9. private static int cal(int m, int n) {
  10. if (m <= 1 || n == 1) {
  11. return 1;
  12. }
  13. if (m < n) {
  14. return cal(m, m);
  15. } else {
  16. return cal(m - n, n) + cal(m, n - 1);
  17. }
  18. }
  19. }

但是递归解法自顶向下,效率很低,如果画一下递归调用栈,会发现存在大量的重复计算,提交也会超时。。。

这时候就可以用动态规划来解,同样的思路,只不过是反过来自底向上。
用一个二维数组来存放每次的计算结果,以方便复用,而这个数组的base就是当i、j小于等于1的时候,arr[i][j]=1:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Scanner sc = new Scanner(System.in);
  4. while (sc.hasNext()) {
  5. int num = sc.nextInt();
  6. System.out.println(dp(num, num));
  7. }
  8. }
  9. private static int dp(int m, int n) {
  10. int[][] arr = new int[m + 1][n + 1];
  11. for (int i = 0; i <= m; i++) {
  12. for (int j = 0; j <= n; j++) {
  13. if (i <= 1 || j <= 1) {
  14. arr[i][j] = 1;
  15. } else if (i < j) {
  16. arr[i][j] = arr[i][i];
  17. } else {
  18. arr[i][j] = arr[i - j][j] + arr[i][j - 1];
  19. }
  20. }
  21. }
  22. return arr[m][n];
  23. }
  24. }

提交一下,完美通过。

JAVA 用分苹果来理解本题的更多相关文章

  1. Java实现 蓝桥杯VIP 算法训练 猴子分苹果

    问题描述 秋天到了,n只猴子采摘了一大堆苹果放到山洞里,约定第二天平分.这些猴子很崇拜猴王孙悟空,所以都想给他留一些苹果.第一只猴子悄悄来到山洞,把苹果平均分成n份,把剩下的m个苹果吃了,然后藏起来一 ...

  2. Java实现 蓝桥杯VIP 算法提高 分苹果

    算法提高 分苹果 时间限制:1.0s 内存限制:256.0MB 问题描述 小朋友排成一排,老师给他们分苹果. 小朋友从左到右标号1-N.有M个老师,每次第i个老师会给第Li个到第Ri个,一共Ri-Li ...

  3. 蓝桥杯 算法训练 ALGO-121 猴子分苹果

      算法训练 猴子分苹果   时间限制:1.0s   内存限制:256.0MB 问题描述 秋天到了,n只猴子采摘了一大堆苹果放到山洞里,约定第二天平分.这些猴子很崇拜猴王孙悟空,所以都想给他留一些苹果 ...

  4. 【转】关于Java的Daemon线程的理解

    原文地址:http://www.cnblogs.com/ChrisWang/archive/2009/11/28/1612815.html 关于Java的Daemon线程的理解 网上对Java的Dae ...

  5. COJN 0583 800602分苹果

    800602分苹果 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放, ...

  6. Java内存管理的进一步理解-模拟过程图解

    Java内存管理的进一步理解-模拟过程图解--转载 java的内存管理分为: 1.堆内存:2.栈内存:3.方法区:4.本地方法区 /* 1:方法区      方法区存放装载的类数据信息包括:      ...

  7. C语言 · 分苹果

    算法提高 分苹果   时间限制:1.0s   内存限制:256.0MB      问题描述 小朋友排成一排,老师给他们分苹果. 小朋友从左到右标号1..N.有M个老师,每次第i个老师会给第Li个到第R ...

  8. java 重写你可以这么理解 因为 方法名和参数类型个数相同 所以这就是重写了 然后 因为是重写 所以 返回值必须相同

    java  重写你可以这么理解    因为   方法名和参数类型个数相同  所以这就是重写了    然后  因为是重写  所以  返回值必须相同

  9. Java中线程同步的理解 - 其实应该叫做Java线程排队

    Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...

  10. Java ClassLoader加载机制理解 实际例子

    针对 Java ClassLoader加载机制理解, 做了个如何自定制简单的ClassLoader,并成功加载指定的类. 不废话,直接上代码. package com.chq.study.cl; im ...

随机推荐

  1. HCNP Routing&Switching之IP安全

    前文我们了解了DHCP安全相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16637627.html:今天我们来聊一聊IP安全相关话题: 技术背景 随着 ...

  2. 搭建docker镜像仓库(二):使用harbor搭建本地镜像仓库

    目录 一.系统环境 二.前言 三.Harbor 四.使用harbor搭建私有镜像仓库 4.1 环境介绍 4.2 k8smaster节点安装配置harbor 4.2.1 安装harbor离线包 4.2. ...

  3. UTL_FILE 包使用介绍

    Postgresql 不支持 package功能,这给oracle 向 postgresql迁移增加了很多迁移工作.人大金仓Kingbase数据库实现了类似 oracle package 功能,并提供 ...

  4. 接口测试神器Apifox,亲测好用!

    自己关注的公众号比较多,之前有收到过有关 Apifox 的文章,自己也是大致看看,还没有用过它! 最近看到比较多有关 Apifox 的文章,所以自己就花了点时间去研究它,使用完后发现确实比Postma ...

  5. ProxySQL(10):读写分离方法论

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9318558.html 不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,ProxySQL当然也支 ...

  6. ProxySQL(2):初试读写分离

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9278839.html 实现一个简单的读写分离 这里通过一个简单的示例实现ProxySQL的读写分离功能,算是 ...

  7. 2流高手速成记(之三):SpringBoot整合mybatis/mybatis-plus实现数据持久化

    接上回 上一篇我们简单介绍了基于SpringBoot实现简单的Web开发,本节来看Web开发中必不可少的内容--数据持久化 先看项目结构: 1. 创建数据表 打开mysql,打开数据库 test (没 ...

  8. 数据结构与算法【Java】08---树结构的实际应用

    前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...

  9. Es 学习笔记 (1)

    目录 前言 什么是es? es数据组织类比 应用场景 核心概念 集群 节点(node) 索引(Index) 文档类型(Type) 文档(Document) Mapping 核心简单域类型 分片(sha ...

  10. java常用注解校验参数

    validation中内置的constraints 注解 描述 @AssertFalse 所注解的元素必须是Boolean类型,且值为false @AssertTrue 所注解的元素必须是Boolea ...