数的划分
思路:在本题中我尝试了一下用递归写的dp,记忆化建立了一张表。
dp【x】【y】【z】中,x代表需要分配的数,y以后代表分数时不能超过y,z代表还剩下几次分配机会。
dp方程为 dp[x][y][z]=求和{dp[x-k][k][z-1]}(k从y至1)(需要注意:k是从y开始的,需要把x-k<0的情况continue掉。)
需要注意 分配不完 和 分配不够两种情况。
当z>x 时,不够分,dp为0。当z==x,恰好够分,dp[x][y][z]=1;
当x>y*z时,分配不完,dp为0。相等时,dp[x][y][z]=1;
dfs时需要注意,当z==0&&x==0时,分配完成,return 1;
#include<iostream>
using namespace std;
int n,k;
int dp[201][201][7];
int dfs(int x,int y,int z){
if(z==0&&x==0)return 1;
if(dp[x][y][z]!=-1)return dp[x][y][z];
if(z>x){
dp[x][y][z]=0;
// cout<<x<<" "<<y<<" "<<z<<": "<<0<<endl;
return 0;
}
else if(z==x){
dp[x][y][z]=1;
// cout<<x<<" "<<y<<" "<<z<<": "<<1<<endl;
return 1;
}
else if(x>y*z){
dp[x][y][z]=0;
// cout<<x<<" "<<y<<" "<<z<<": "<<0<<endl;
return 0;
}
else if(x==y*z){
dp[x][y][z]=1;
// cout<<x<<" "<<y<<" "<<z<<": "<<1<<endl;
return 1;
}
int res=0;
for(int k1=y;k1>=1;k1--){
if(x-k1<0)continue;
res+=dfs(x-k1,k1,z-1);
}
dp[x][y][z]=res;
// cout<<x<<" "<<y<<" "<<z<<": "<<res<<endl;
return dp[x][y][z];
}
int main(){
cin>>n>>k;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
for(int l=0;l<=k;l++){
dp[i][j][l]=-1;
}
}
}
cout<<dfs(n,n,k)<<endl;
return 0;
}