Description
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
Input
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
Output
对输入的每组数据M和N,用一行输出相应的K。
Sample Input
1
7 3
Sample Output
8
解题思路:
定义dp[i][j] := j的i划分的总数,对应于本问题则是将j个苹果放到i个盘子中的总的分法个数
考虑j的i划分,用Ak来表示第k个盘子中的物品数量
∑
k
=
1
i
A
i
 
=
j
\sum_{k=1}^{i}\ A_i\,=j
k=1∑i Ai=j
1、如果对于所有的盘子,都有Ak > 0,那么从每个盘子中都拿去一个物品,就是 j-i 的 i 划分;
2、如果存在物品数为0的盘子,这便对应了j 的 i-1 划分。
得到动态规划方程如下:
if (j >= i) {//盘子数不大于物品数,两种情况都可能存在
dp[i][j] = dp[i - 1][j] + dp[i][j - i];
}
//盘子比物品还多,则一定有空盘子
else dp[i][j] = dp[i - 1][j];
不要忘记初始化:我的理解是把0个物品放在 i 个盘子上,那么只有所有的盘子都为空这一种放法。把i个物体放在0个盘子上,则没有相应的放法。
for (int i = 1; i <= 10; i++) {//不要忘记初始化!!!
dp[i][0] = 1; dp[0][i] = 0;
}
AC代码
#include<iostream>
using namespace std;
int dp[11][11];
int main() {
int t, m, n;//m个苹果 n 个盘子
cin >> t;
for (int i = 1; i <= 10; i++) {//不要忘记初始化!!!
dp[i][0] = 1; dp[0][i] = 0;
}
for (int i = 1; i <= 10; i++) {
for (int j = 1; j <= 10; j++) {
if (j >= i) {
dp[i][j] = dp[i - 1][j] + dp[i][j - i];
}
else dp[i][j] = dp[i - 1][j];
//cout << i << " " << j << " " << dp[i][j] << endl;
}
}
while (t--) {
cin >> m >> n;
cout << dp[n][m] << endl;
}
}