题目链接:
https://www.acwing.com/problem/content/11/
#背包问题
和最短路求方案数的思路差不多
用二维的举例:(f[i][j]
转移完后)
- 如果
f[i][j]==f[i-1][j]
:g[i][j]+=f[i-1][j]
- 如果
f[i][j]==f[i-1][j-v[i]]
:g[i][j]+=f[i-1][j-v[i]]
对于不同的状态定义方式,f
和g
数组的初始化也不同
这里采用前i个物品不超过体积j的定义方式
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010,mod=1e9+7;
int f[N],g[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<=m;i++) g[i]=1;//初始化时我们易知,不论是哪个体积下,总有一个对应的最大价值,方案数为1
for(int i=1;i<=n;i++)
{
int v,w;
cin>>v>>w;
for(int j=m;j>=v;j--)
{
if(f[j]<f[j-v]+w)
{
g[j]=g[j-v]; //当f[j]<f[j-v]+w时,说明g[j]只能从上层转移过来了
f[j]=f[j-v]+w;
}
else if(f[j]==f[j-v]+w) g[j]=(g[j]+g[j-v])%mod;//若相等,说明存在了2个节点,他们路径都符合条件
//可以递推到g[j]
}
}
cout<< g[m] <<endl;//最后输出这个体积不超过m对应最大价值的方案数即可!
return 0;
}