DFS+DP两种方法
本蒟蒻的第一篇题解,希望大家能看懂
一 DFS解法
我最开始的想法就是写一个DFS,比较简单。
last代表这次划分的数,循环时从last开始,就可以避免重复了。
ni代表还需要分的数
ki代表还需要分的份数
每次分到ni/ki就够了,否则后面就不够分了
#include<iostream>
using namespace std;
int v[201][7]={},n,k;
int dp(int last,int ni,int ki)
{
if(ki==1) return 1;
int s=0;
for(int i=last;i<=ni/ki;i++)
s+=dp(i,ni-i,ki-1);
return s;
}
int main()
{
cin>>n>>k;
cout<<dp(1,n,k);
}
二、DP解法
这个是看了其他大佬的解法后写出来的,本蒟蒻之前没有想到,看到其他大佬的题解比较难理解(可能是本蒟蒻太弱了),所以我也写上我的理解。
(引用一下另一个大佬的题解)
“solution【i】【j】代表在数的和为i的情况下分为j组共有的情况数。由于无论在数的和为几时,把它们分成0组都是0种情况,分成一组都是一种情况,所以j=0时全部要初始化为0,j=1时全部要初始化为1。同时,无论共分为几组,数的和为0和1是0种情况(i=j=1除外)所以i=0或i=1时j从2开始全部初始化为0。对于剩下的任意一个solution【i】【j】(i>=j),都可以用如下方式求得:solution【i】【j】=第一个数为1的所有情况+第一个数不为1的所有情况。”
第一个数为1时,1占用了1个位置并且划分为1个区域,因此,第一个数为1的所有情况=solution【i-1】【j-1】。
第一个数不为1时,可以视为先在位置上都加上一个1,因为分出1后剩下 i-j可分的1,还需分j份,所以占有了总数j个,位置仍然是j个(solution【i-j】【j】)。
综上所述,solution【i】【j】=solution【i-1】【j-1】+solution【i-j】【j】。
#include<iostream>
using namespace std;
int main()
{
int n,k,solution[201][7]={};
cin>>n>>k;
for(int i=0;i<n;i++)
solution[i][0]=0,solution[i][1]=1;
for(int i=2;i<k;i++)
solution[0][k]=0,solution[1][k]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
if(j>i) solution[i][j]=0;
else solution[i][j]=solution[i-1][j-1]+solution[i-j][j];
cout<<solution[n][k];
}