Gift Hunting
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1743 Accepted Submission(s): 581
Problem Description
After winning two coupons for the largest shopping mart in your city, you can't wait inviting your girlfriend for gift hunting. Having inspected hundreds of kinds of souvenirs, toys and cosmetics, you
finally narrowed down the candidate list to only n gifts, numbered 1 to
n. Each gift has a happiness value that measures how happy your girlfriend would be, if you get this gift for her. Some of them are special - you
must get it for your girlfriend (note that whether a gift is special has nothing to do with its happiness value).
Coupon 1 can be used to buy gifts with total price not greater than V1 (RMB). Like most other coupons, you can’t get any money back if the total price is strictly smaller than V1. Coupon 2 is almost the same, except that it’s worth V2. Coupons should be used separately. That means you cannot combine them into a super-coupon that’s worth V1+V2. You have to divide the gifts you choose into two part, one uses coupon 1, the other uses coupon 2.
It is your girlfriend's birthday today. According to the rules of the mart, she can take one (only one) gift for FREE! Here comes your challenge: how to make your girlfriend as happy as possible?
Coupon 1 can be used to buy gifts with total price not greater than V1 (RMB). Like most other coupons, you can’t get any money back if the total price is strictly smaller than V1. Coupon 2 is almost the same, except that it’s worth V2. Coupons should be used separately. That means you cannot combine them into a super-coupon that’s worth V1+V2. You have to divide the gifts you choose into two part, one uses coupon 1, the other uses coupon 2.
It is your girlfriend's birthday today. According to the rules of the mart, she can take one (only one) gift for FREE! Here comes your challenge: how to make your girlfriend as happy as possible?
Input
There will be at most 20 test cases. Each case begins with 3 integers
V1, V2 and n (1 <= V1 <= 500, 1 <= V2 <= 50, 1 <=
n <= 300), the values of coupon 1 and coupon 2 respectively, and the number of candidate gifts. Each of the following
n lines describes a gift with 3 integers: P, H and
S, where P is the price, H is the happiness (1 <= P,H <= 1000),
S=1 if and only if this is a special gift - you must buy it (or get it for free). Otherwise
S=0. The last test case is followed by V1 = V2 = n = 0, which should not be processed.
Output
For each test case, print the case number and the maximal total happiness of your girlfriend. If you can't finish the task, i.e. you are not able to buy all special gifts even with the 1-FREE bonus, the
happiness is -1 (negative happiness means she's unhappy). Print a blank line after the output of each test case.
Sample Input
3 2 4 3 10 1 2 10 0 5 100 0 5 80 0 3 2 4 3 10 1 2 10 0 5 100 0 5 80 1 0 0 0
Sample Output
Case 1: 120 Case 2: 100
题意:有两张优惠券分别为v1,v2,和一次免费特权,你女朋友生日,问你用以上条件去退换礼物,每个礼物有一定的幸福指数,且有些礼物你必须买,如果特殊礼物不能全买输出-1,否则输出你能为你女朋友买到的最大的幸福指数。
解题思路:
每个物品只有两种选择方案,买或者不买,所以一想到是0-1背包,但是这题不是纯背包,是背包的变异。我们可以这样想,用两张优惠券分别去购买(并行着),假设dp[0,1][v1][v2],0表示还没有用免费机会,1 表示用了免费的机会,那么dp[0][v1][v2] 表示花了v1,v2还没使用免费的机会获得的最大的幸福指数,dp[1][v1][v2]表示用了免费的机会获得的最大的幸福指数。最后只要判断dp[1][v1][v2]是否大于0即可。
详细见代码:
<span style="font-size:18px;"> #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f3
using namespace std;
int dp[2][505][55];
int p[310],h[310],s[310];
int main()
{
int v1,v2,n,cas=0;
while(~scanf("%d %d %d",&v1,&v2,&n) && v1+v2+n){
for(int i=1;i<=n;i++){
scanf("%d %d %d",&p[i],&h[i],&s[i]);
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
int w=p[i],v=h[i];
for(int j=v1;j>=0;j--){
for(int k=v2;k>=0;k--){
int ans=dp[0][j][k];
if(s[i]==0){
dp[1][j][k]=max(dp[1][j][k],ans+v);
if(j>=w){
dp[0][j][k]=max(dp[0][j][k],dp[0][j-w][k]+v);
dp[1][j][k]=max(dp[1][j][k],dp[1][j-w][k]+v);
}
if(k>=w){
dp[0][j][k]=max(dp[0][j][k],dp[0][j][k-w]+v);
dp[1][j][k]=max(dp[1][j][k],dp[1][j][k-w]+v);
}
}
else{
dp[1][j][k]=ans+v;
if(j>=w && k>=w){
dp[0][j][k]=max(dp[0][j][k-w],dp[0][j-w][k])+v;
dp[1][j][k]=max(dp[1][j][k-w],dp[1][j-w][k])+v;
}
else if(j>=w){
dp[0][j][k]=dp[0][j-w][k]+v;
dp[1][j][k]=max(dp[1][j-w][k]+v,dp[1][j][k]);
}
else if(k>=w){
dp[0][j][k]=dp[0][j][k-w]+v;
dp[1][j][k]=max(dp[1][j][k-w]+v,dp[1][j][k]);
}
else dp[0][j][k]=-INF;
}
}
}
}
printf("Case %d: %d\n\n",++cas,dp[1][v1][v2]<0 ? -1 : dp[1][v1][v2]);
}
return 0;
}
</span>