hdu3236Gift Hunting【二维01背包】

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?

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 

机智的我虽然看出是这个分类依旧卡了3个多点的题,状态好次==

题意:给女朋友买一堆礼物,每个礼物有一个快乐值,有n个备选的,其中有一部分是必买的,总共有两张支票,价值v1,v2,花钱少了不给退,两张支票不能凑在一起用,而且有一个礼物是免费的,问女友最多可以多快乐?

做法:最开始的思路是:dp[v1][v2],三重循环,一维是礼物,二维、三维分别是dp的两维,然后循环的时候犯了一个低级错误,j,k正常来说是大于cost[i]循环到cost[i[就停止了,但是这个题不能停啊!比方说j循环到cost[i[停了,但是k不一定不满足啊,这个题是两维啊!

然后,题中要求有一个是免费的,我受之前做过的题(貌似是饭卡吧)的影响,纠结于是要找出一个最贵的还是最快乐的?觉得是应该找出来一个“快乐值”最大的,然而并不是的。这个题的处理方法是再加一维dp表示是否用过这个免费的机会(貌似之前树形dp做过吧)之后,dp转移是很容易可以想到的==

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int cost1[309],hap1[309],cost0[309],hap0[309],dp[505][55][2],n,v1,v2;
int main()
{
   // freopen("cin.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int cas=1;
    while(~scanf("%d%d%d",&v1,&v2,&n))
    {
        if(v1==0&&v2==0&&n==0)break;
        memset(dp,0,sizeof(dp));
        int l0=0,l1=0,maxh=0,maxn;
        for(int i=0;i<n;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(c==1)
            {
                cost1[l1]=a;
                hap1[l1++]=b;
                maxh+=b;
            }
            if(c==0)
            {
                cost0[l0]=a;
                hap0[l0++]=b;
            }
        }
        for(int i=0;i<l1;i++)
        {
            for(int j=v1;j>=0;j--)
            {
                for(int k=v2;k>=0;k--)
                {
                    dp[j][k][1]=max(dp[j][k][1],dp[j][k][0]+hap1[i]);
                    if(j>=cost1[i])
                        dp[j][k][0]=max(dp[j][k][0],dp[j-cost1[i]][k][0]+hap1[i]),
                        dp[j][k][1]=max(dp[j][k][1],dp[j-cost1[i]][k][1]+hap1[i]);
                    if(k>=cost1[i])
                        dp[j][k][0]=max(dp[j][k][0],dp[j][k-cost1[i]][0]+hap1[i]),
                        dp[j][k][1]=max(dp[j][k][1],dp[j][k-cost1[i]][1]+hap1[i]);
               //     printf("i=%d,j=%d,k=%d,dp0=%d,dp1=%d\n",i,j,k,dp[j][k][0],dp[j][k][1]);
                }
            }
        }
        if(dp[v1][v2][1]<maxh)maxn=-1;
        else
        {
            for(int i=0;i<l0;i++)
            {
                for(int j=v1;j>=0;j--)
                {
                    for(int k=v2;k>=0;k--)
                    {
                        if(dp[j][k][0]>=maxh)
                            dp[j][k][1]=max(dp[j][k][1],dp[j][k][0]+hap0[i]);
                        if(j>=cost0[i]&&dp[j-cost0[i]][k][0]>=maxh)
                            dp[j][k][0]=max(dp[j][k][0],dp[j-cost0[i]][k][0]+hap0[i]);
                        if(j>=cost0[i]&&dp[j-cost0[i]][k][1]>=maxh)
                            dp[j][k][1]=max(dp[j][k][1],dp[j-cost0[i]][k][1]+hap0[i]);
                        if(k>=cost0[i]&&dp[j][k-cost0[i]][0]>=maxh)
                            dp[j][k][0]=max(dp[j][k][0],dp[j][k-cost0[i]][0]+hap0[i]);
                        if(k>=cost0[i]&&dp[j][k-cost0[i]][1]>=maxh)
                            dp[j][k][1]=max(dp[j][k][1],dp[j][k-cost0[i]][1]+hap0[i]);
                    //    printf("i=%d,j=%d,k=%d,dp0=%d,dp1=%d\n",i,j,k,dp[j][k][0],dp[j][k][1]);
                    }
                }
            }
            maxn=dp[v1][v2][1];
        }
        printf("Case %d: %d\n\n",cas++,maxn);
    }
    return 0;
}
时间: 2024-10-10 21:21:03

hdu3236Gift Hunting【二维01背包】的相关文章

hdu3496 二维01背包

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3496 //刚看题目以为是简单的二维01背包,but,,有WA点.. 思路:题中说,只能买M个光盘,不能多也不能少,所以就要求把背包装满. 恰好把背包装满,那么在初始化时,除了dp[0]=0,剩下的dp[1~M],均为负无穷(其实设置成-1,到时候在判断一下也是一样的,思想相同) 这样才可以保证最终得到的dp[M]是一种恰好装满背包状态的最优解. 代码: #include<iostream

宠物小精灵之收服 (二维01背包)

[题目链接] http://noi.openjudge.cn/ch0206/4978/ [算法] 做的第一道二维的背包问题,只需开的数组增加一维以正确表述每一个状态即可.本质还是多过程决策+最优子结构+无后效性. [代码] 1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m,k,i,j,t,minm; 4 int v[1010],u[510],dp[1010][510]; 5 int main() 6 { 7 scanf(&q

poj3260 平衡问题(二维01背包)

http://www.cnblogs.com/ziyi--caolu/p/3228090.html http://blog.csdn.net/lyy289065406/article/details/6648094/ 这道题更加理解了背包问题实质上是状态的转换. 范围中有负数,先平移到全是正数,因为最后所有砝码都要用上,所以可以先遍历第一个的所有情况,再以此推出第二个. 上面的思路用穷举是不行的,所以这时就要用DP,而背包正好很适合解决这一类问题,这就是解题的突破口 #include <iost

POJ - 1948 二维01背包

T了两发,DP方程很简单粗暴 dp[i][j][k]:用前i物品使得容量分别为j和k的背包恰好装满 背包的调用只需一次即可,第一次T就是每次check都丧心病狂地背包一次 对于sum的枚举,其实i j枚举到sum/2就可以了 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define scan(a) scanf(

POJ2184Cow Exhibition(二维费用背包)

Cow Exhibition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9067   Accepted: 3441 Description "Fat and docile, big and dumb, they look so stupid, they aren't much fun..." - Cows with Guns by Dana Lyons The cows want to prove to t

HDU-2159FATE(二维完全背包)

FATE Problem Description 最 近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完 这最后一级.现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度.当忍耐 度降到0或者0以下时,xhd就不会玩这游戏.xhd还说了他最多只杀s只怪.请问他能升掉这最后一级吗? Input 输 入数据有多组,对于每组数据第一行输入

hdu3496+poj1948(二维费用背包)

Watch The Movie Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 5106    Accepted Submission(s): 1614 Problem Description New semester is coming, and DuoDuo has to go to school tomorrow. She dec

HDU 2159 FATE【二维多重背包】

大意:二维多重背包 分析:二维多重背包 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 105; 8 int dp[maxn][maxn]; 9 int a[maxn], b[maxn]; 10 11 int main() { 12 int n,

HDU2159 二维完全背包

FATE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12533    Accepted Submission(s): 5932 Problem Description 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级.现在的问