hdu 4091 Zombie’s Treasure Chest 贪心+枚举

转自:http://blog.csdn.net/a601025382s/article/details/12308193

题意:

输入背包体积n,绿宝石体积s1,价值v1,蓝宝石体积s2,价值v2,宝石数目无限,问背包里能放下的最大价值?

题解:

看过去很像完全背包,可数据很大(虽然没给出,也能猜到,不然太水了),所以不能用背包求。又只有两种物品,想到了贪心,将价值与体积比大(称为价值比)的优先放入。但体积限制,这样还不可以,还需要枚举减少价值比大的宝石个数,是否可以增大所求价值。又我们可以知道对于体积是m=lcm(s1,s2)背包,肯定全选价值比大的。所以至多只要枚举n-n/m+m的体积。如果小于这个值,存在大于m的空余,这个空余肯定用价值大的放置。

注意:

1.不够一个公倍数的时候,计算需要小心。。我就出错了。。

2.枚举的时候,跨度选择max(s1,s2),这个算是优化吧,没有的话会TLE

 

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #include<set>
 10 #include<string>
 11 //#include<pair>
 12 
 13 #define N 10000005
 14 #define M 1005
 15 #define mod 1000000007
 16 //#define p 10000007
 17 #define inf 0x3f3f3f3f
 18 #define mod2 100000000
 19 #define ll long long
 20 #define LL long long
 21 #define maxi(a,b) (a)>(b)? (a) : (b)
 22 #define mini(a,b) (a)<(b)? (a) : (b)
 23 
 24 using namespace std;
 25 
 26 ll n,s1,v1,s2,v2;
 27 ll ans;
 28 ll ma;
 29 ll g;
 30 ll c1,c2;
 31 ll ans1,ans2;
 32 
 33 ll gcd(ll a,ll b)
 34 {
 35     return b==0?a:gcd(b,a%b);
 36 }
 37 ll lcm(ll a,ll b)
 38 {
 39     return a/gcd(a,b)*b;
 40 }
 41 
 42 void ini()
 43 {
 44     ans=0;
 45     ans1=ans2=0;
 46     scanf("%I64d%I64d%I64d%I64d%I64d",&n,&s1,&v1,&s2,&v2);
 47     g=lcm(s1,s2);
 48     c1=g/s1;
 49     c2=g/s2;
 50 }
 51 
 52 
 53 
 54 void solve()
 55 {
 56     if(n/g>=1)
 57         ans1=(n/g-1)*max(c1*v1,c2*v2);
 58     ll i;
 59     if(s1<s2){
 60         swap(c1,c2);
 61         swap(s1,s2);
 62         swap(v1,v2);
 63     }
 64     ll left=n%g;
 65     if(n/g>=1)
 66         left+=g;
 67     ll en=left/s1;
 68     ll re;
 69     for(i=0;i<=en;i++){
 70         re=i*v1+(left-i*s1)/s2*v2;
 71         ans2=max(ans2,re);
 72     }
 73     ans=ans1+ans2;
 74 }
 75 
 76 void out()
 77 {
 78     printf("%I64d\n",ans);
 79 }
 80 
 81 int main()
 82 {
 83     int T;
 84     //freopen("data.in","r",stdin);
 85     //freopen("data.out","w",stdout);
 86     scanf("%d",&T);
 87     for(int ccnt=1;ccnt<=T;ccnt++)
 88    // while(T--)
 89    // while(scanf(""))
 90     {
 91         //if(n==0 && k==0 ) break;
 92 
 93         ini();
 94         solve();
 95         printf("Case #%d: ",ccnt);
 96         out();
 97     }
 98 
 99     return 0;
100 }

 

转载于:https://www.cnblogs.com/njczy2010/p/4039664.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值