华为OJ平台——放苹果(典型整数划分问题)

题目描述:

输入m,n,分别表示苹果数与盘子的总数,要求输出苹果放在n个盘子的方法总数(注意511和151是一种情况),例如输入 7 3 输出8((7),(6,1),(5,2),(4,3),(5,1,1),(4,2,1),(3,3,1),(3,2,2))

思路:

最典型的解法整数分解,例如给定n个苹果,把苹果放到k个盘子里,允许有的盘子为空,不妨设 f(n , k ) (边缘条件为当 n = 0 ,1时,返回1,当 k = 1 时,返回1)表示结果,分析一下可以知道有两种放的方法,一种是有空盘,一种是没空盘。

没空盘的情况可以知道每个盘子里至少有一个苹果,也就是说这种情况的总数为 f ( n-k , k ) 。

而有空盘的情况,我们可以假设最后一个盘子为空,则这种情况的总数为f ( n , k-1 ) (无需考虑多个盘子为空的情况,递归时必然会出现)

所以状态转移方程为 f ( n , k ) = f ( n-k , k ) + f ( n , k-1 )

 1 import java.util.Scanner;
 2
 3 /**
 4  * 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,
 5  * 问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
 6  */
 7 public class PlayApples {
 8
 9     public static void main(String[] args) {
10         //输入读取参数
11         Scanner cin = new Scanner(System.in) ;
12         int apples = cin.nextInt() ;
13         int planes = cin.nextInt() ;
14         cin.close();
15
16         System.out.println(count(apples,planes)) ;
17
18     }
19
20     /**
21      * 最典型的整数分解
22      * 例如给定n个苹果,把苹果放到k个盘子里,允许有的盘子为空, 不妨设 f(m , n )
23      * (边缘条件为当 m == 0 ,1时,返回1,当 n == 1 时,返回1)表示结果,
24      * 分析一下可以知道有两中放的方法,一种是有空盘,一种是没空盘,
25      * 没空盘的情况可以知道每个盘子里至少有一个苹果,也就是说这种情况的总数为 f ( n-k , k ) 。
26      * 而有空盘的情况,我们可以假设最后一个盘子为空,则这种情况的总数为f ( n , k-1 ) (无需考虑多个盘子为空的情况,递归时必然会出现)
27      * 所以状态转移方程为 f ( n , k ) = f  ( n-k , k ) +  f ( n , k-1 )。
28      *
29      * 而如果是不允许有空盘子的情况,则可以由上面的情况推出,
30      * 设 d ( n , k ) 表示把n个苹果放到k个盘子里,不允许有空盘子的方法总数,
31      * 则有f ( n , k ) =  Σ (  1 <= i <= k ) d ( n , i )
32      * 所以 d ( n , k ) = f ( n , k ) - f ( n , k-1 )
33      *
34      * @param m  苹果数量
35      * @param n  盘子数量
36      * @return
37      */
38     private static int count(int m, int n) {
39         //n为0 是错误的,故返回0
40         if(n == 0){
41             return 0 ;
42         }
43         //m == 0,1时和 n == 1时均只有一种放法
44         if(m == 0 || n == 1 || m == 1 ){
45             return 1 ;
46         }else if(m < 0){
47             //m < 0 时,也是错误的情形,所以返回0
48             return 0 ;
49         }else{
50             //递归调用
51             return count(m-n,n) + count(m,n-1) ;
52         }
53     }
54 }

Code

扩展:

而如果是不允许有空盘子的情况,则可以由上面的情况推出,设 d ( n , k ) 表示把n个苹果放到k个盘子里,不允许有空盘子的方法总数,则有

f ( n , k ) = Σ ( 1 <= i <= k ) d ( n , i ) 所以 d ( n , k ) = f ( n , k ) - f ( n , k-1 )

时间: 2024-10-11 17:04:26

华为OJ平台——放苹果(典型整数划分问题)的相关文章

华为OJ:2041 放苹果

这道题难点不在于代码怎么写,而是思路怎么想.感觉一般这种题要么你理好一个思路要么你最后总结出一个公式,要么你自己模拟它的运作方式,用迭代,或者递归的方式来做.有点像我们以前学的排列组合. 对于m个苹果,n个盘子f(m,n),如果苹果个数比盘子少,那么就跟n个盘子,n个苹果是一样的f(n,n).如果m比n大,那么有两种情况,一种有空盘子的情况,一种没有空盘子的情况,两种情况不重叠且加一起一定为情况总数.第一种情况就即为n个盘子放在m-1个盘子里,因为至少有个空盘子.f(m,n-1),第二种情况下,

华为OJ之放苹果

题目描述: 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法.输入每个用例包含二个整数M和N.0<=m<=10,1<=n<=10.<=n<=10<=m<=10样例输入7 3样例输出8 题目分析: 本题实际上是一个划分问题,借助于递归这个强大的工具,我们可以比较容易地进行解决,具体分析思路如下: 1,我们用f(m, n)来表示m个苹果,n个篮子的情况; 2,出口条件:当m &l

华为OJ平台——字符串分隔

题目描述: 连续输入字符串,请按长度为8拆分每个字符创 后输出到新的字符串数组: 长度不是8整数倍的字符串请在后面补数字0,空字符串不处理 输入 连续输入字符串(输入两次,每个字符长长度小于100)输出 输出到长度为8,的新字符串数组样例输入 abc 123456789样例输出 abc00000 12345678 90000000 思路: 都是直接处理,没有具体的方法而言 注意点: 华为的OJ平台的输入输出有点坑,好多次的程序都在这里出问题,在Eclipse上运行的结果没问题,然后在OJ上就是编

华为OJ平台——矩阵乘法

题目描述: 如果A是个x行y列的矩阵,B是个y行z列的矩阵,把A和B相乘,其结果将是另一个x行z列的矩阵C. 输入: 1.第一个矩阵的行数 2.第一个矩阵的列数(也是第二个矩阵的行数) 3.第二个矩阵的列数 4.第一个矩阵的值 5.第二个矩阵的值 输出: 输出两个矩阵相乘的结果 样例输入 2 2 2 3 8 8 0 9 0 18 9 样例输出 171 72 72 0 思路: 题目意思很简单,只是实现两个矩阵乘法功能,要注意的一点是输出的格式. OJ平台中对输出的格式非常严格,经过多次尝试,验证此

华为OJ平台——查找组成一个偶数最接近的两个素数

1 import java.util.Scanner; 2 3 /** 4 * 问题描述:任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况, 5 * 本题目要求输出组成指定偶数的两个素数差值最小的素数对,其中 5 < n <= 10000 6 * eg:输入20,输出7 13 7 */ 8 public class PrimePair { 9 10 public static void main(String[] args) { 11 Scanner cin = ne

华为OJ平台——求最大连续bit数

题目描述: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1 输入: 一个byte型的数字    输出: 对应的二进制数字中1的最大连续数 思路: 通过移位运算可以一次判断每一位的0.1值,然后通过统计可以得到结果 import java.util.Scanner; //byte 的范围是-128~127 public class MaxContinueOne { public static void main(String[] args) {

华为OJ平台——尼科彻斯定理

题目描述: 验证尼科彻斯定理,即:任何一个整数m的立方都可以写成m个连续奇数之和. 例如: 1^3=1 2^3=3+5 3^3=7+9+11 4^3=13+15+17+19 输入 输入一个int整数 输出 输出分解后的string 样例输入 6 样例输出 31+33+35+37+39+41 思路: 由例子1~4给出的结论猜测  n3 = (n*(n-1)+1) + (n*(n-1)+2 +1) + ... + (n*(n+1)-2 + 1 )(共n项,等差数列,差为2) 而又等差数列的性质知:

【华为OJ平台练习题】求最后一个单词长度

//描述 //计算字符串最后一个单词的长度,单词以空格隔开. //知识点 字符串,循环 //运行时间限制 0M //内存限制 0 //输入 //一行字符串,长度小于128. //输出 //整数N,最后一个单词的长度. //样例输入 hello world //样例输出 5 #include <iostream> using namespace std; int countLastWordLength(char *s) { int counter=0; int lg = strlen(s); f

华为OJ平台试题 —— 数组:字符串反转

字符串反转 代码: /* * 接受一个字符串,然后输出该字符串反转后的字符串. */ #include <stdio.h> #include <string.h> /* * 字符串反转函数 */ char *revstr(char *str, int len) { char *start = str; char *end = str + len - 1; char ch; if (str != NULL) { while (start < end) { ch = *start