HDU-4091
题意:T次输入,每次输入背包容量n,绿宝石体积s1,价值v1,蓝宝石体积s2,价值v2,宝石无限,问背包的最大价值。
思路:因为数据可以很大,所以不能用完全背包求。两个物品,想到贪心,将性价比高的优先放入背包;但由于背包容量限制,还需要枚举减少性价比高的物品,加入性价比低的物品,也许能增大背包价值。
我们知道,对于体积是m=lcm(s1,s2)背包,肯定全选性价比高的。所以至多只要枚举n-n/m+m的体积。其余肯定用性价比高的放置。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<math.h>
#include<algorithm>
using namespace std;
#define LL __int64
LL gcd(LL a, LL b)
{
if(a > b) swap(a,b);
return a==0 ? b : gcd(b%a,a);
}
LL lcm(LL a, LL b)
{
return b/gcd(a,b)*a;
}
int main()
{
int T;
LL n, s1, s2, v1, v2;
scanf("%d",&T);
for(int j = 1; j <= T; j++)
{
cin >> n >> s1 >> v1 >> s2 >> v2;
LL m = lcm(s1,s2);
LL k = n/m;
if(k) k--;
LL ans = 0;
n = n - k*m; //需要枚举的空间
if(s1 < s2) //让1号物品是体积大的那个,便于后面枚举
{
swap(v1,v2);
swap(s1,s2);
}
for(LL a = 0; a*s1 <= n; a++)//枚举体积大的物品数量
{
ans = max(ans, a*v1+(n-s1*a)/s2*v2);
}
if(v1*s2 < v2*s1) //让1号物品是性价比高的那个,为了后面计算
{
swap(v1,v2);
swap(s1,s2);
}
ans += k*(m/s1)*v1;
printf("Case #%d: %I64d\n",j,ans);
}
return 0;
}