混合背包
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
#include <iostream> #include <string.h> #include <algorithm> const int PMAX = 200002;//背包最大容量 int N,C;//N种物品和一个容量为C的背包 //物品最多有M件可用,重量是W,价值是V int W[PMAX],V[PMAX],M[PMAX]; int dp[PMAX];//记录总价值 using namespace std; int main() { while(cin >> N >> C) { //N个物品,背包体积为C memset(dp,0,sizeof(dp)); int sum,k=0; //m=1表示至多取一件,m=-1表示可以数量无限 for(int i=1;i<=N;i++){ cin >> W[i] >> V[i] >> M[i]; sum=1; //将多重背包转换为0-1背包 if(M[i]>1){ while(M[i]>sum){ k++; W[N+k]=W[i]*sum; V[N+k]=V[i]*sum; M[N+k]=1; M[i]-=sum; sum*=2; } W[i]*=M[i]; V[i]*=M[i]; M[i]=1; } } for(int i=1;i<=N+k;i++){ //0-1背包 if(M[i]==1){ for(int j=C;j>=W[i];j--) dp[j]=max(dp[j],dp[j-W[i]]+V[i]); } //完全背包 else{ for(int j = W[i];j<=C;j++) dp[j]=max(dp[j],dp[j-W[i]]+V[i]); } } cout<<dp[C]<<endl; } return 0; }