将m个相同的球全部放到n个相同的盒子里面有几种放法,盒子不能为空,m>=n
盒子不能为空,所以可以当成将m-n个球放到n个盒子里,盒子可以为空。
比如将10个球放到5个盒子里,可以当成5个球放到5个盒子里,盒子能为空。接着,再分情况,将球分为
(5,0,0,0,0)
(4,1,0,0,0)或(2,3,0,0,0)
(3,1,1,0,0)或(2,2,1,0,0)
(2,1,1,1,0)
(1,1,1,1,1)
也就是1个盒子不能为空,2个盒子不能为空,3个盒子不能为空,到5个盒子都不能为空。
是不是跟一开始的时候很像,m个球放到n个盒子不能为空?这时候想到了什么?对,递归。
用一个函数fun(m,n)来获取m个球放到n个盒子里不能为空的情况(也可以用能为空的,这里用的是不能为空的)
上面的可以转换成
fun(5,1)+fun(5,2)+fun(5,3)+fun(5,1)+fun(5,0) //其中n为0的情况即刚好每个盒子分到一个球,这个也要算进去
如果有非递归方法的,欢迎提出来探讨^_^,我自己的理解,不知道对错,有错请指出,谢谢!
//============================================================================ // Name : test.cpp // Author : AstrayLinux //============================================================================ #include <iostream> using namespace std; int fun(int m, int n) { if (m < n) //m<n返回0 return 0; if (n == 1 || (m - n) <= 1) //盒子为1时,球只有一个或0(0个即球刚好均分),时都只有一种分配方法 return 1; int s = 0, count; //s记录总数,count为递归次数 if (m - n < n) //去掉每个盒子分配的一个球后,球的数量少于盒子数,则只要递归球的个数次 count = m - n; //球数少的情况 else count = n; //盒子数少的情况 for (int i = 1; i <= count; i++) { s += fun(m - n, i); //递归 } return s; } int main(int argc, char **argv) { cout << "\t"; for (int i = 1; i <= 15; i++) { cout << i << "\t"; } cout << endl; for (int i = 1; i <= 15; i++) { cout << i << "\t"; for (int j = 1; j <= 15; j++) { cout << fun(i, j) << " "; } cout << endl; } } //下面是结果 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 //2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 //3 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 //4 1 2 1 1 0 0 0 0 0 0 0 0 0 0 0 //5 1 2 2 1 1 0 0 0 0 0 0 0 0 0 0 //6 1 3 3 2 1 1 0 0 0 0 0 0 0 0 0 //7 1 3 4 3 2 1 1 0 0 0 0 0 0 0 0 //8 1 4 5 5 3 2 1 1 0 0 0 0 0 0 0 //9 1 4 7 6 5 3 2 1 1 0 0 0 0 0 0 //10 1 5 8 9 7 5 3 2 1 1 0 0 0 0 0 //11 1 5 10 11 10 7 5 3 2 1 1 0 0 0 0 //12 1 6 12 15 13 11 7 5 3 2 1 1 0 0 0 //13 1 6 14 18 18 14 11 7 5 3 2 1 1 0 0 //14 1 7 16 23 23 20 15 11 7 5 3 2 1 1 0 //15 1 7 19 27 30 26 21 15 11 7 5 3 2 1 1