https://www.luogu.org/problemnew/show/P1025
题目描述
将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5
1,5,1
5,1,1
问有多少种不同的分法。
输入输出格式
输入格式:
n,k (6<n≤200,2≤k≤6)
输出格式:
1个整数,即不同的分法。
输入输出样例
输入样例#1: 复制
7 3
输出样例#1: 复制
4
说明
四种分法为:
1,1,5
1,2,4
1,3,3
2,2,3
思路:递推,本题相当于把n个球放到k个盒子里面,可能有两种情况:(1)至少有1个盒子中有1个小球。那么相当于把n-1个球放到k-1个盒子中;(2)任意一个盒子的小球个数都大于等于2。那么相当于把n-k个球放到k个盒子中且满足n>=2*k。综上我们可得到递推式:f[n][k]=f[n-1][k-1]+f[n-k][k](n>=2*k) 当n<2*k的时候,只有前半部分。
(递推是大坑啊orz)
#include<iostream>
using namespace std; //动态规划题解
//该问题相当于把n个小球放到k个盒子里面
//(1)至少有一个盒子只有一个小球 因为盒子不分顺序
//所以相当与 把n-1个小球放到k-1个盒子里面
//(2)没有一个盒子只有一个小球 即所有盒子都至少两个球
//则相当于把n-k个球放到k个盒子里面(且n>=2*k)
//f[n][k]=f[n-1][k-1]+f[n-k][k]
int n,k,f[205][10];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
f[i][1]=1;
for(int i=2;i<=n;i++)
for(int j=2;j<=k;j++)
{
if(i>=2*j)
f[i][j]=f[i-1][j-1]+f[i-j][j];
else
f[i][j]=f[i-1][j-1];
}
cout<<f[n][k]<<endl;
return 0;
}