 /**//*
题意:给出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;
}
|