/**//* 题意:给出n个物品,其中有一些必买,有v1,v2容量的背包2个 求最大价值 还有可以免费选一个 如果不是免费选一个的话 dp0[j,k]表示不一定买的物品装在[j,k]容量的背包的最大价值 dp1[j,k]表示必买的物品装在[j,k]容量的背包的最大价值 然后二维背包即可 最后答案就是max{dp1[j,k]+dp0[v1-j,v2-k]} 需dp1[j,k]=total(必买物品价值总和)
但现在多了个免费的物品 可以加状态!方便做很多! _dp0[j,k]表示不一定买的物品装在[j,k]容量的背包的最大价值,同时里面有一个免费物品 _dp1[j,k]表示必买的物品装在[j,k]容量的背包的最大价值,同时里面有一个免费物品 最后答案就是max{dp1[j,k]+_dp0[v1-j,v2-k],_dp1[j,k]+dp0[v1-j,v2-k]} */ #include<cstdio> #include<algorithm> #include<cstring>
using namespace std;
struct Gift { int p,h,s; bool operator<(const Gift&B)const { return s<B.s; } }gift[305];
int _dp0[505][55],dp0[505][55]; int _dp1[505][55],dp1[505][55];
int main() { //freopen("in","r",stdin); int n,v1,v2,t=1; while(scanf("%d%d%d",&v1,&v2,&n),n) { for(int i=0;i<n;i++) scanf("%d%d%d",&gift[i].p,&gift[i].h,&gift[i].s); sort(gift,gift+n);
memset(_dp0,0,sizeof(_dp0)); memset(dp0,0,sizeof(dp0)); memset(_dp1,0,sizeof(_dp1)); memset(dp1,0,sizeof(dp1));
//0 int num=0; for(int i=0;i<n&&gift[i].s==0;i++,num++) { int p=gift[i].p,h=gift[i].h; for(int j=v1;j>=0;j--) for(int k=v2;k>=0;k--) { _dp0[j][k]=max(_dp0[j][k],dp0[j][k]+h); if(k>=p) { dp0[j][k]=max(dp0[j][k],dp0[j][k-p]+h); _dp0[j][k]=max(_dp0[j][k],_dp0[j][k-p]+h); } if(j>=p) { dp0[j][k]=max(dp0[j][k],dp0[j-p][k]+h); _dp0[j][k]=max(_dp0[j][k],_dp0[j-p][k]+h); } } }
int total = 0; //1 for(int i=num;i<n;i++) { int p=gift[i].p,h=gift[i].h; total+=h; for(int j=v1;j>=0;j--) for(int k=v2;k>=0;k--) { _dp1[j][k]=max(_dp1[j][k],dp1[j][k]+h); if(k>=p) { dp1[j][k]=max(dp1[j][k],dp1[j][k-p]+h); _dp1[j][k]=max(_dp1[j][k],_dp1[j][k-p]+h); } if(j>=p) { dp1[j][k]=max(dp1[j][k],dp1[j-p][k]+h); _dp1[j][k]=max(_dp1[j][k],_dp1[j-p][k]+h); } } } int ans = -1; for(int j=0;j<=v1;j++) for(int k=0;k<=v2;k++) { if(dp1[j][k]==total) { ans = max(dp1[j][k]+_dp0[v1-j][v2-k],ans); } if(_dp1[j][k]==total) { ans = max(_dp1[j][k]+dp0[v1-j][v2-k],ans); } } printf("Case %d: %d\n\n",t++,ans); } return 0; }
|