题目描述
将整数nn分成kk份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7n=7,k=3k=3,下面三种分法被认为是相同的。
1,1,51,1,5;
1,5,11,5,1;
5,1,15,1,1.
问有多少种不同的分法。
输入输出格式
输入格式:
n,kn,k (6<n≤200,2≤k≤6)
输出格式:
11个整数,即不同的分法。
输入输出样例
输入样例#1:
7 3
输出样例#1:
4
说明
四种分法为:
1,1,5
1,2,4
1,3,3
2,2,3
思路:
典型的递推dp题,虽然也可以用dfs做,因为数据比较小。
当i<x时,有dp[i][x]=0;i==x时,dp[i][x]=1;
对其他的情况,有两种:
1.划分得出的数列有一个为1
2.都不为1
将本题转化为n个球放入k个盒子的问题。
对第一种情况,对接下来的计算相当于剔除一个球和存放该球的盒子,dp[i][j]=dp[i-1][j-1]。
对第二种情况,对每个盒子都取出一个球,相当于把n-k个球放入k个盒子,dp[i][j]=dp[i-j][j]。
所以可得状态转移方程:dp[i][j]=dp[i-1][j-1]+dp[i-j][j](i>j)
代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,k;
scanf("%d %d",&n,&k);
int dp[205][10];
for(int i=1;i<=n;i++){
dp[i][1]=1;
dp[i][0]=1;
}
for(int i=2;i<=k;i++){
dp[1][i]=0;
dp[0][i]=0;
}
for(int i=2;i<=n;i++)
for(int j=2;j<=k;j++){
if(i>j)
dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
else
dp[i][j]=dp[i-1][j-1];
}
printf("%d\n",dp[n][k]);
return 0;
}