问题描述
将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。
例如:n=7,k=3,下面三种分法被认为是相同的。
1,1,5; 1,5,1; 5,1,1;
问有多少种不同的分法。
输入格式
n,k
输出格式
一个整数,即不同的分法
样例输入
7 3
样例输出
4 {四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;}
数据规模和约定
6<n<=200,2<=k<=6
这道题 可以变型为 n个球 k个相同盒子 的组合问题
我们先 推算下面的过程:
根据题意 k 个盒子 必须每一个盒子 都至少有一个球 那么不妨先每一个盒子都放入一个 因为这是必须要做的 此时还剩下n-k个球
那么 此时n-k个球 可以都放入一个盒子中也可以放入两个盒子 ,三个盒子 。。。。。。 k个盒子,那么仔细想一下,此时递推关系是不是已经 出来了 因为 你已经把 n 个球k个盒子的问题 变为了 n-k个球于 分别于 两个盒子,三个盒子,四个盒子。。。
min(k,n-k)个盒子的问题 (这里解释下 为啥是min(k,n-k) 其实很简单举两个例子就行了 n=4 k=2 于 n=104 k=2 带入就明显很多了)
我dp不好 这个还是看一位大佬的 下面附上链接: 很厉害的大佬
https://blog.csdn.net/liangzihao1/article/details/54644933
我的行和列都是从1 开始的 以前没咋尝试 dp 感觉这样用比较好
#include <iostream>
#include <math.h>
using namespace std;
int dp[250][10];
int n,k;
int main()
{
cin >>n>>k;
//init
int i,j,h;
for(i=1;i<=k;i++)
{
dp[1][i]=i>1? 0:1;
}
//dp 填表
for(i=2;i<=n;i++)
{
for(h=1;h<=k;h++)
{
if(i==h)
{
dp[i][h]=1;
continue;
}
for(j=1;j<=min(h,i-h);j++)
{
dp[i][h]+=dp[i-h][j];
}
}
}
cout << dp[n][k];
return 0;
}