题目是要把一个正整数划分为若干正整数的和
例如 5=1+1+1+1+1
=2+1+1+1
=2+2+1
=3+1+1
=3+2
=4+1
=5
这就是样例的七种
实际可以感觉到有点像完全背包那个味道了,可以把正整数看成一个物品,可以无限选择
但是和背包问题不同的是背包只需要装下物品即不大于背包体积
而这道题目则是可以类比于物品的体积和等于背包的体积
区别就要体现在初始化状态数组中了
一维写法用f[i][j]表示前i个数字中选并且和是j的集合 属性就是方案数
首先初始化的时候f[0][0]=1 也就是和为0且从前0个数开始选没有方案也是一种方案
这里也就是和完全背包问题的区别, 完全背包求最大值不选的时候价值显然是0
#include<iostream>
using namespace std;
const int N=1010,mod=1e9+7;
int f[N][N];
int n;
//f[i][j]=f[i-1][j]+f[i-1][j-i]+f[i-1][i-2i]
//f[i][j-i]= f[i-1][j-i]+f[i-1][i-2i]
//差了一项f[i-1][j]
int main()
{
cin>>n;
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)
{
f[i][j]=f[i-1][j]%mod;
if(j>=i)f[i][j]=(f[i-1][j]+f[i][j-i])%mod;
}
cout<<f[n][n]<<endl;
return 0;
}
上述代码中注解可以很好的诠释当j>=i的时候是如何进行转换的和完全背包差不多就不多赘述了
然后可以优化为一维的也和完全背包类似
不需要修改j的循环方向
#include<iostream>
using namespace std;
const int N=1010,mod=1e9+7;
int f[N];
int n;
//f[i][j]=f[i-1][j]+f[i-1][j-i]+f[i-1][i-2i]
//f[i][j-i]= f[i-1][j-i]+f[i-1][i-2i]
//差了一项f[i-1][j]
int main()
{
cin>>n;
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
f[j]=(f[j]+f[j-i])%mod;
}
cout<<f[n]<<endl;
return 0;
}