思路:
- 题目分析:明显这是一道不为空的“分垛题”。两种方法:搜索法(只适用小数据)和递推法(都适用~)
- 搜索法:一垛一垛选择,为了避免重复(1、1、5;1、5、1;5、1、1)不妨设立一个规则:只选择不递减序列。(这样的话只有1、1、5才是合法的)
- 递推法:
- 设dp[i][j]代表刚好将i个果子分成j个垛(抽象化)。
- 为了保证每垛非空,首先将j个垛都先“铺”上一个果子。
- 此时还剩下i-j个果子,我们再选择是将i-j个果子分为1个垛,还是2个垛,还是3个垛······还是j个垛
- 3.不要忘记啦,每个垛都没有特殊标记的!所以按照以上两操作,我们就已经保证不重不漏咯~
代码展示:
(1)搜索法
#include<stdio.h>
#include<stdlib.h>
long long search(int sum,int f,int min)
{
//sum:此时还剩多少个果子
//f:要将剩余的sum个果子分为多少份
//min:当前分的这一垛至少要多少个果子(保证为不递减序列)
int i;
//剪枝
if(sum<0) return 0;
//结束条件
if(f==0)
{
if(sum==0) return 1;
return 0;
}
long long jg=0;
for(i=min;i<=sum;i++)
{
jg+=search(sum-i,f-1,i);
}
return jg;
}
int main()
{
int n,k,t;
scanf("%d %d",&n,&k);
printf("%lld",search(n,k,1));
return 0;
}
(2)递推法
#include<stdio.h>
#include<stdlib.h>
long long dp[205][10];//dp[i][j] 将i个果子分成非空的j垛 有多少种方案
int main()
{
int n,k;int i,j,t;
scanf("%d %d",&n,&k);
dp[0][0]=1;//便于后面的计算
for(i=1;i<=200;i++)
{
for(j=1;j<=6&&j<=i;j++)
{
//计算将i个果子分为j垛的方案数
dp[i][j]=0;//初始化
for(t=0;t<=j;t++)//将剩余的i-j个果子分为t垛
{
dp[i][j]+=dp[i-j][t];
}
}
}
printf("%lld",dp[n][k]);
return 0;
}