背包问题求方案数
求出恰好为j的背包问题的价值,然后合计所以最大价值的方案数。
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e3+10,mod = 1e9+7;
int f[N];
int g[N];
int main() {
int n,m;
cin>>n>>m;
memset(f,-0x3f,sizeof f);
f[0] = 0;//恰好为0
g[0] = 1;
for(int i = 0;i< n ;i++){
int v,w;
cin>>v>>w;
for(int j = m;j>=v;j--){
int maxv = max(f[j],f[j-v]+w);
int cnt = 0;
if(maxv == f[j]) cnt +=g[j];
if(maxv == f[j-v]+w) cnt +=g[j-v];
g[j] = cnt%mod;
f[j] = maxv;
}
}
int res = 0;
for(int i = 0;i<=m;i++) res = max(res,f[i]);//最大价值
int cnt = 0;
for(int i= 0;i<=m;i++){//求最大价值的方案数之和
if(res ==f[i])
cnt = (cnt+g[i]) %mod;
}
cout<<cnt;
return 0;
}
能量石
思路:贪心加01背包恰好dp,关键在于理解背包的体积和价值,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 1e4+10,N = 1e2+10;
int f[M];
struct stone{
int s,e,l;
bool operator< (const stone w) const{
return s*w.l<l*w.s;
}
}s[N];
int main() {
int T;
cin>>T;
for(int i = 1;i<=T;i++){
int m = 0,n;
cin>>n;
for(int j = 1;j<=n;j++){
scanf("%d%d%d",&s[j].s,&s[j].e,&s[j].l);
m+=s[j].s;
}
sort(s+1,s+1+n);
memset(f,-0x3f,sizeof f);
f[0] =0;
for(int j = 1;j<=n;j++){
for(int k = m;k>=s[j].s;k--){
f[k] = max(f[k],f[k-s[j].s]+s[j].e-(k-s[j].s)*s[j].l);
}
}
int res = 0;
for(int j = 1;j<=M;j++){
res = max(res,f[j]);
}
printf("Case #%d: %d\n",i,res);
}
return 0;
}