(1)放苹果:M个同样的苹果放N个同样的盘子,允许有盘子空着, 问有多少种放法。
注意:5 1 1和1 5 1是同一种放法
分析:
分两种情况:
a.至少有一个盘子为空。此时放法种数与减去这个空盘子的放法种数相同。
b.所有盘子都不为空。此时可以从每个盘子里拿掉一个苹果而不影响放法种数。
显然m<n时,只能满足第一种情况.
很好的算法: f(m, n) = f(m-n, n) + f(m, n-1)
f(m, n): 把m个苹果放到n个盘子中的方法数 f(m, n-1): 把m个苹果放到n-1个盘子中的方法数(其中至少有一个空盘子) f(m-n, n): 把m个苹果放到n个盘子中,而且每个盘子中都有苹果(先拿n个出来,等m-n个放好了,然后每个盘子放一个)
1 int PlaceApple(int m, int n) 2 { 3 if(m < 0) 4 return 0; 5 if(m == 0) //每个盘子一个 6 return 1; 7 if(n == 1) //只有一个盘子 8 return 1; 9 return PlaceApple(m - n, n) + PlaceApple(m, n - 1); 10 }
(2)计算3个A,2个B可以组成多少种排列的问题(如:AAABB, AABBA)是《组合数学》的研究领域。但有些情况下,也可以利用计算机计算速度快的特点通过巧妙的推理来解决问题。下列的程序计算了m个A,n个B可以组合成多少个不同排列的问题。请完善它。
int f(int m, int n) { if(m==0 || n==0) return 1; return f(m-1, n) + f(m, n-1); }
分析:首先明确这个函数的功能是:求m个A和n个B可以组成多少种排列。
此时分两种情况: a.排列的第一个元素是A。 b.排列的第一个元素是B。
把这两种情况的排列种数加起来即可.
(3)某布袋中有红球m个,白球n个,现在要从中取出x个求,红球数目多于白球的数目的概率是多少。下面的代码解决这个问题,其中y表示红球至少要出现的次数。
分析:明确函数的定义:求m个红球、n个白球的布袋中取出x个球,红球数目大于白球的概率。注意到m/(m+n)表示取出的球是红球的概率,n/(m+n)表示取出的球是白球的概率。现在从布袋中取一个球出来
有两种情况:
a.取出的是红球
b.取出的是白球.
然后根据不同的情况判断m、n、x、y的变化。
1 代码: 2 //m个红球,n个白球,从中取出x个求,y表示红球至少要出现的次数 3 double f( int m, int n, int x,int y) 4 { 5 if(y>x) return 0; 6 if(y==0) return 1; 7 if(y>m) return 0; 8 if(x-n>y) return 1; 9 /* 10 m/(m+n)表示第一次选红球,随后的就重复了 11 */ 12 double p1 = f(m-1,n,x-1,y-1); 13 double p2 = f(m,n-1,x-1,y); 14 return (double)m/(m+n)*p1+(double)n/(m+n)*p2; 15 }
4)假设有m+n个人,其中,m个人手持面额为5角的硬币,n个人手持面额为1元的硬币,他们都要乘车买票,现假设售票员手中无零钞,票价为5角,下面这个函数就可以算出这m+n个人所有可能的买票情况(顺利
完成购票过程的购票次序的种类数),请完善此函数 int f(int m, int n) { if(m < n) return 0; if(n==0) return
1; return f(m-1 , n) + f( m , n-1) ;}
一般的想法是从前往后发现规律,但这题确是从后考虑。
分两种情况:
(1)最后一个上车的,持有1元硬币。 前m+n-1个人有:f(m,n-1)
(2)最后一个上车的,持有0.5元硬币。 前m+n-1个人有:f(m-1,n)
(5)整数划分
如,对于正整数n=6,可以分划为:
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1+1
总共有十一种划分,求一个数总共有多少种这样的划分。
根据n和m的关系,考虑以下几种情况:
(1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
(2) 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
(3) 当n=m时,根据划分中是否包含n,可以分为两种情况:
(a). 划分中包含n的情况,只有一个即{n};
(b). 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此 f(n,n) =1 + f(n,n-1);
(4) 当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);
(5) 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
(a). 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分
个数为f(n-m, m);
(b). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);
因此 f(n, m) = f(n-m, m)+f(n,m-1);
综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于回归条件,(3)和(4)属于特殊情况,将会转换为情况(5)。而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。其递推表达式如下:
f(n, m)= 1; (n=1 or m=1)
f(n, n); (n<m)
1+ f(n, m-1); (n=m)
f(n-m,m)+f(n,m-1); (n>m)