题目链接:UVA12325
12325 - Zombie's Treasure ChestTime limit: 3.000 seconds |
数学题
第一眼以为是傻逼DP 然后发现数据量真大。。
后来想了一下 还是比较水的。
题意是给你两种物品 价值V1,V2 大小S1,S2 让你用一个大小是C的背包去装
求最大价值。数据在int范围内(10^9数量级)
首先很容易想到如果比较大的背包的大于sqrt(C)的话 一定能在sqrt(C) 的复杂度内得到正解
因为可以枚举这个物品放多少个 最多sqrt(C) 个
如果没有可以通过证明一个结论来搞 如果背包大小为 lcm(S1,S2) 那么一定是全装性价比最高的那种物品这个方案更优
这结论比较好证就不说了 然后通过这个结论
可以得到一个枚举算法 先把所有背包用来装性价比高的那种物品 然后再用另一种物品替换 知道替换的容量超过lcm(S1,S2)就停止
记录过程中的最大价值 就是最优解
然后这种算法在 lcm(S1,S2) 比较大时 枚举次数会很多
综合上面两个算法 就能解决这个问题了~
设S1>S2
如果 S1>50000 就用第一种算法来搞 即枚举大容量物品的个数 最多枚举C/S1次 (最坏10^4左右)
如果 S1<50000 就用第二种算法来搞 即枚举S2次替换 (最坏10^4左右)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
// freopen("1.txt","r",stdin);
int t,ti=1;
scanf("%d",&t);
while(t--)
{
printf("Case #%d: ",ti++);
long long c,c1,c2,v1,v2;
scanf("%lld%lld%lld%lld%lld",&c,&c1,&v1,&c2,&v2);
if(c1>c2) swap(c1,c2),swap(v1,v2);
if(c2>50000)
{
long long ans=0;
for(int i=0;i*c2<=c;i++)
ans=max(ans,(c-i*c2)/c1*v1+i*v2);
printf("%lld\n",ans);
}
else
{
if(v1*c2>v2*c1) swap(v1,v2),swap(c1,c2);
long long ans=0;
for(int i=0;i<=c2 && c-i*c1>=0;i++)
ans=max(ans,(c-i*c1)/c2*v2+i*v1);
printf("%lld\n",ans);
}
}
return 0;
}