题意是求最大价值的方案数
最大价值可以有不同方案最后取得的最大价值
这些方案都要加在一起最后取模
首先先把最大价值求出来(简单的01背包)
然后关键的是每一种组合的方案数还不知道
需要求
求完之后,如果f[m]等于最大价值了,直接就把此时对应的m方案数相加取模就可以
那方案数依然通过一个集合来求
f[i][j]是体积恰好是j的最大价值(这里初始化和范围不要弄错)
那令g[i][j]是体积恰好是j的方案数(还有方案数初始化是1,最大价值才是0(可以想明白))
根据f来推导g
f有两种:
选还是不选,这里的方案数是最优解也就是最大价值的方案数,如果最大价值在不选的情况里面,就加前面的部分,反之则加选的哪个部分
下面看代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e6+10,mod=1e9+7;
int f[N],g[N];
int main(){
int n,m;
cin>>n>>m;
memset(f,-0x3f,sizeof(f));
f[0]=0;
g[0]=1;
for(int i=1;i<=n;i++)
{
int v,w;
cin>>v>>w;
for(int j=m;j>=v;j--)
{
int cnt=0;//每一次的方案数
int maxn=max(f[j],f[j-v]+w);
if(maxn==f[j]) cnt+=g[j];
if(maxn==f[j-v]+w) cnt+=g[j-v];
f[j]=maxn;
g[j]=cnt%mod;
}
}
int mx=-1,res=0;
for(int i=0;i<=m;i++) mx=max(mx,f[i]);
for(int i=0;i<=m;i++)
{
if(mx==f[i])
res=(res+g[i])%mod;
}
cout<<res<<"\n";
return 0;
}