HDU_4091_Zombie’s Treasure Chest_最小公倍数、机智地枚举

来源:互联网 发布:mac安装win10分区 编辑:程序博客网 时间:2024/05/09 22:43

被队友卖了去给集训队买车票再见


题意:

超大背包,有两种物品,大小分别为s1,s2,价值分别为v1,v2,背包容积为n,问最大获取价值



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.


背包DP果断不行,数据太大了,还是康康机智,想出了优化办法。

先找出s1,s2的最小公倍数m,占用m空间时的最优解是确定的,要么全装第一个物品,要么全装第二个物品,n/m*m的空间都用这种方法完成,剩下的空间暴力枚举即可。

最小公倍数很快,算结果O(1)即可。剩余空间小于m,存在关系sqrt(m)<min(max(s1,s2),sqrt(10^9)),遍历需要m/max(s1,s2)次操作,小于min( max(s1,s2), sqrt(10^9) ),所以肯定可以快速解决。


代码如下:

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;#define LL long longLL max( LL a, LL b ){if( a >= b )return a;else return b;} LL gcd( LL a, LL b ){return b == 0 ? a : gcd( b, a % b );}LL lcm( LL a, LL b ){return a / gcd( a, b ) * b;}int main(){int t;int ss = 0;scanf("%d",&t);while( t-- ){long long v, s1, s2, v1, v2;printf("Case #%d: ",++ss);scanf("%I64d%I64d%I64d%I64d%I64d",&v,&s1,&v1,&s2,&v2);if( s1 < s2 ){int tmp=s1;s1=s2;s2=tmp;tmp=v1;v1=v2;v2=tmp;}long long L = lcm( s1, s2 );long long c = v % L;if(  L > v ){LL ans = 0;for( long long i = 0; i <= c / s1; ++i ){ans = max( ans, i * v1 + ( c - s1 * i ) / s2 * v2 );}printf("%I64d\n",ans);}else{LL ans = 0;for( long long i = 0; i <= (c + L) / s1; ++i ){ans = max( ans,  i * v1 + (  c + L - s1 * i ) / s2 * v2 );}ans += ( v - L ) /  L * max( L / s1 * v1, L / s2 * v2 );printf("%I64d\n",ans);}}}


0 0
原创粉丝点击