HDU 4091 Zombie’s Treasure Chest(贪心+枚举)

9 篇文章 0 订阅
7 篇文章 1 订阅

Zombie’s Treasure Chest

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6378    Accepted Submission(s): 1333


Problem Description
  Some brave warriors come to a lost village. They are very lucky and find a lot of treasures and a big treasure chest, but with angry zombies.
  The warriors are so brave that they decide to defeat the zombies and then bring all the treasures back. A brutal long-drawn-out battle lasts from morning to night and the warriors find the zombies are undead and invincible.
  Of course, the treasures should not be left here. Unfortunately, the warriors cannot carry all the treasures by the treasure chest due to the limitation of the capacity of the chest. Indeed, there are only two types of treasures: emerald and sapphire. All of the emeralds are equal in size and value, and with infinite quantities. So are sapphires.
  Being the priest of the warriors with the magic artifact: computer, and given the size of the chest, the value and size of each types of gem, you should compute the maximum value of treasures our warriors could bring back.
 

Input
  There are multiple test cases. The number of test cases T (T <= 200) is given in the first line of the input file. For each test case, there is only one line containing five integers N, S1, V1, S2, V2, denoting the size of the treasure chest is N and the size and value of an emerald is S1 and V1, size and value of a sapphire is S2, V2. All integers are positive and fit in 32-bit signed integers.
 

Output
  For each test case, output a single line containing the case number and the maximum total value of all items that the warriors can carry with the chest.
 

Sample Input
  
  
2 100 1 1 2 2 100 34 34 5 3
 

Sample Output
  
  
Case #1: 100 Case #2: 86
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   4099  4097  4096  4095  4098 

题目大意:

    求所有数据不超过int的只有两个物品的的多重背包。


解题思路:

    一道巨大的背包问题,感觉又回到了以前不会背包碰到背包的时候。

    首先贪心,一定是优先取性价比高的物品。当然大家都知道这一定是错的,于是我们就需要再枚举减少的数目。这时就可以找到一个枚举的下限,就是max(0,(总重量/两个物品重量的最小公倍数-1)*每个最小公倍数中第一个物品的个数)。

    首先证明一下为什么这样是对的。每一个最小公倍数都可以完全用两种背包的任意一个来填满,所以我们只需要一个最小公倍数快来和剩下的进行枚举即可。

    接下来证明一下为什么这样会比较快。当物品重量比价小时,最小公倍数也比较小,所以最后剩下的部分+一个最小公倍数也很小。而当物品重量比较大时,物品的个数很少,我们需要枚举的次数也就很少。

    讨论区说这题的数据有点迷,我也感觉到了,在我的代码中有一个小于等于理论上换成小于是不会有任何问题的,但它就是WA了,害得我dubug了好几个小时。。。


AC代码:

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <string.h>
#include <cstdio>
#include <map>
#include <queue>
#include <math.h>
#include <cstring>
#include <set>
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;

LL N,w1,v1,w2,v2;

LL gcd(LL a,LL b)//求最大公因数
{
    if(b==0)return a;
    return gcd(b,a%b);
}

int main()
{
    LL T,cas=1;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld%lld%lld%lld",&N,&w1,&v1,&w2,&v2);
        LL lca=w1/gcd(w1,w2)*w2;//最小公倍数
        if(v1*1.0/w1<v2*1.0/w2)
        {
            swap(v1,v2);
            swap(w1,w2);
        }
        LL low=max(0ll,(N/lca-1)*lca);//枚举的下限
        LL num1=N/w1,num2=(N-num1*w1)/w2,ans=num1*v1+num2*v2;
        if(w1>=w2)//非常奇怪,去掉等号就会WA,但理论上取不取等是完全一样的
            for(LL i=num1;i*w1>=low;i--)  
                ans=max(ans,i*v1+(N-i*w1)/w2*v2);
        else
        {
            for(LL i=num2;(N-i*w2)/w1*w1>=low;i++)
                ans=max(ans,i*v2+(N-i*w2)/w1*v1);
        }  
        printf("Case #%lld: %lld\n",cas++,ans);
    }
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值