Description
背包体积为C,给出N个物品,每个物品占用体积为Vi,价值为Wi,每个物品要么至多取1件,要么至多取Mi件(Mi > 1),要么数量无限,在所装物品总体积不超过C的前提下所装物品的价值的和的最大值是多少?
Input
多测试用例。
第一行两个数N和C(C ≤ 200000,N ≤ 200),下面N行每行三个数Vi,Wi,Mi分别表示每个物品的体积、价值与数量,Mi=1表示至多取一件,Mi>1表示至多取Mi件,Mi=-1表示数量无限。
Output
输出一行结果:所装物品价值的最大值。
Sample Input
2 10
3 7 2
2 4 -1
Sample Output
22
AC代码:
#include <iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define LL long long using namespace std; const int maxn = 200000+10; const int maxc = 1e9+7; LL f[maxn]; int v[210],w[210],m[210]; int n,V; void ZeroOnePack(int cost,int weight)//0-1背包 { for(int j=V;j>=cost;j--) f[j]=max(f[j],f[j-cost]+weight); } void CompletePack(int cost ,int weight)//完全背包 { for(int j=cost;j<=V;j++) f[j]=max(f[j],f[j-cost]+weight); } void MultiPack(int cost,int weight,int amount)//多重背包 { if(cost*amount>=V) { CompletePack(cost,weight); return; } int k=1; while(k<amount) { ZeroOnePack(k*cost,k*weight); amount-=k; k*=2; } ZeroOnePack(amount*cost,amount*weight); } int main() { while(scanf("%d%d",&n,&V)!=EOF) { memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) scanf("%d %d %d",&v[i],&w[i],&m[i]); for(int i=1;i<=n;i++) { if(m[i]==1)//0-1背包 { ZeroOnePack(v[i],w[i]); } else if(m[i]==-1)//完全背包 { CompletePack(v[i],w[i]); } else //多重背包 { MultiPack(v[i],w[i],m[i]); } } cout<<f[V]<<endl; } return 0; }