 /**//*
題意:給出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;
}
|