题目:
Description
圣诞节到了,圣诞老人给 N 个小朋友准备了 M 个礼物。每个小朋友有一个袜子(袜子不编号,无区别, 认为袜子都相同), 圣诞老人将 M 个礼物装到 N 个袜子中的放法有多少种? 注意: 1)若M=7 N=3,那么5,1,1的放法和1,5,1的放法算是同一种装法。 2)允许袜子为空。 3)M和N无大小关系,M可以比N大,M也可以比N小。
输入格式
输入数据包含两个整数 M,N。1<=M,N<=50。
M在前,N在后,中间空格。
输出格式
输出共有几种不同的放法。
输入样例
7 3
输出样例
8
解题思路:
用递推方式:设d[i][j]表示有i个礼物,备份给j个小朋友。
我理解的是首先题目说明可以让袜子里面为空,那么分配出来的种类就有空袜子组合+不为空袜子组合;然后空袜子组合就相当于相同礼物个数分配少一个袜子,那么就是和d[i][j-1]的分类个数相等。如果没有空袜子组合,那么就相当于袜子里面礼物的基数是1,可以想想如果每个袜子里面都必须有1个礼物,那么这N个礼物不就不会影响分配的种类数了吗?
讨论袜子是否为空:
袜子不为空:d[i][j]=d[i-j][j];
袜子为空:d[i][j]=d[i][j-1];
最后得出d[i][j]=d[i][j-1]+d[i-j][j];
然后就是要写出临界的:
d[i][0]=0,i>=1; d[i][1]=1,i>=1; d[0][j]=1, j>=1
答案:
int main(void)
{
int M,N;
scanf("%d %d",&M,&N);
int d[M+1][N+1];
for(int i=1;i<=M;i++)
{
d[i][0]=0;
}
for(int j=1;j<=N;j++)
{
d[0][j]=1;
}
for(int i=1;i<=M;i++)
{
for(int j=1;j<=N;j++)
{ if(i<j)
{
d[i][j]=d[i][j-1];
}
else
{
d[i][j]=d[i][j-1]+d[i-j][j];
}
}
}
printf("%d",d[M][N]);
return 0;
}