题目描述
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
输入描述:
每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
输出描述:
对输入的每组数据M和N,用一行输出相应的K。
示例1
输入
复制
1 7 3
输出
复制
8
思路:
dp[i][j]表示把前i个苹果放入j个盘子的方案数。
边界:
dp[0][i]=1 刚开始每个盘子里都是0个苹果,这样初始化是为后续在每个盘子都同时放一块苹果做准备
dp[i][1]=1 只有一个盘子时,所有苹果放在一个盘子,有一种分配方案
状态转移方程:
- 如果i<=j,则最少有j-i个盘子为空,所以dp[i][j]=dp[i][i]
- 若i>j,
- 若无空盘子,从每个盘子里取出一个苹果,方案数不会变。dp[i][j]=dp[i-j][j]
- 若有空盘子,至少有一个盘子是空,dp[i][j]=dp[i][j-1]
- dp[i][j]=dp[i-j][j]+dp[i][j-1]
#include<iostream>
using namespace std;
int dp[100][100]; //a[i][j]表示i个苹果放到j个盘子里的方案数
int main(){
int m,n;
while(scanf("%d%d",&m,&n)!=EOF){ //m个苹果n个盘子
for(int i=0;i<=n;i++){
dp[0][i]=1; //先初始化,刚开始每个盘子里都是0,为后续在每个盘子都一起放一块苹果做准备
}
for(int i=0;i<=m;i++){ //所有苹果放入一个盘子,有一种放法
dp[i][1]=1;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(i<j) dp[i][j]=dp[i][i]; //苹果数小于盘子数,可以看成直接把空盘子去了
else{ //分没有空盘子(=从每个盘子里取出来一个剩下的分配方案数)和you空盘子两种情况
dp[i][j]=dp[i-j][j]+dp[i][j-1];
}
}
}
printf("%d\n",dp[m][n]);
}
return 0;
}