|
|||
描述 | |||
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法(用K表示)?注意:5,1,1和1,5,1是同一种分发。 | |||
关于输入 | |||
第一行是测试数据的数目t(0<= t <= 20),其后的t行均包含两个整数M和N,以空格分开。 1<= M <= 25; 1<= N <= 10; |
|||
关于输出 | |||
对输入的每组数据M和N,用一行输出相应的K | |||
例子输入 | |||
1
|
|||
例子输出 | |||
8
|
|||
提示 | |||
采用递归思想解题。 |
代码:
1 //放苹果问题 2 //2019-11-18 3 #include<iostream> 4 using namespace std; 5 //跟数的划分一个思路,小区别在于允许有空的篮子。可以用搜索或者动规 6 int m, n; //把m划分为n份 7 int ans; //用于存答案 8 void dfs(int step,int x, int left){ //子问题需要用什么参数刻画?划分到第step个数,还剩x +当前数是几 9 if(step==n-1&&x>=left){ //如果已经划分到倒数第二个数了,并且剩下的数比当前数大,就成为一种分法 10 ans++; 11 } 12 else{ 13 for(int i = left; i <= x; i++) //还需要知道当前划分出的数是几,来决定i从几开始循环.i表示分出来的下一个数是啥 14 dfs(step+1,x-i,i); 15 } 16 } 17 int main(){ 18 int t; 19 cin>>t; 20 while(t--){ 21 ans = 0; //注意多组数据输入时的初始化 22 cin>>m>>n; 23 dfs(0,m,0); 24 cout<<ans<<endl; 25 } 26 return 0; 27 }
备注:
这道题和https://www.cnblogs.com/fangziyuan/p/5934345.html这道数的划分是类似的。唯一的区别在于是否能有空篮子,但这也不重要,不管是对动规还是搜索。
对于动规来说,动态转移方程和不能有0就有一点变化:(转+改)
设f[m][n]为将m分成最多n份的方案数,且其中的方案不重复。
则有:
f[m][n] = f[m][n - 1] + f[m - n][n];
= 1 // m== 0 || n == 1
= 0 // m < 0
f[m][n - 1]相当于第一盘子中为0,只用将数分成n - 1份即可。因为0不会大于任何数,相当于f[m][n - 1]中的方案前面加一个为0的盘子,而且不违背f的定义。所以f[m][n - 1]一定是f[m][n]的方案的一部分,即含有0的方案数。
f[m - n][n]相当于第一个盘子不为0.那么把每个盘子的数-1,方案数是不变的,相当于用n个数去凑m-n