网址如下:
Zombie's Treasure Chest - UVA 12325 - Virtual Judge (vjudge.net)
一道枚举题
先上代码:
#include<cstdio>
#include<algorithm>
typedef long long LL;
LL N, S[2], V[2], ans;
void get_ans(int id1, LL end){
ans = 0;
int id2 = id1 ? 0 : 1;
for(LL n1 = 0; n1 <= end; n1++){
LL n2 = (N - n1 * S[id1]) / S[id2];
LL _V = n1 * V[id1] + n2 * V[id2];
ans = ans > _V ? ans : _V;
}
}
int main(void)
{
int T; scanf("%d", &T);
for(int i = 1; i <= T; i++){
scanf("%lld%lld%lld%lld%lld", &N, &S[0], &V[0], &S[1], &V[1]);
LL end, id, e1 = N / S[0], e2 = N / S[1];
id = e1 > e2; end = e1 < e2 ? e1 : e2;
LL LCM = S[0] * S[1] / std::__gcd(S[0], S[1]);
e1 = LCM / S[0]; e2 = LCM / S[1];
int t_id = V[0] * S[1] > V[1] * S[0];
LL e0 = LCM / S[t_id] - 1;
if(e0 < end){end = e0; id = t_id;}
get_ans(id, end);
printf("Case #%d: %lld\n", i, ans);
}
return 0;
}
同样可以解出来的代码:
#include<cstdio>
#include<algorithm>
typedef long long LL;
LL N, S1, V1, S2, V2, LCM, ans;
int main(void)
{
int T; scanf("%d", &T);
for(int i = 1; i <= T; i++){
ans = 0;
scanf("%lld%lld%lld%lld%lld", &N, &S1, &V1, &S2, &V2);
if(S1 < S2){
V1 ^= V2 ^= V1 ^= V2;
S1 ^= S2 ^= S1 ^= S2;
}
LCM = S1 * S2 / std::__gcd(S1, S2);
LL beg, end;
if(V1 * S2 > V2 * S1){
beg = (N - LCM) / S1; beg = beg < 0 ? 0 : beg;
end = N / S1;
}
else{
beg = 0;
end = LCM / S1 - 1; end = end < 0 ? 0 : end;
end = end < (N / S1) ? end : (N / S1);
}
for(LL n1 = beg; n1 <= end; n1++){
LL n2 = (N - n1 * S1) / S2;
LL V = V1 * n1 + V2 * n2;
ans = ans > V ? ans : V;
}
printf("Case #%d: %lld\n", i, ans);
}
}
这两代码的原理是一样的,就是第二个代码在转化的时候出问题了,害的我改了好久
原理:
关键在于减少枚举量,若枚举宝物1的数量,则枚举量为N / S1;枚举宝物2的则是N / S2
求出S1和S2的最小公倍数LCM,即当二者的体积相同的时候,若宝物1的价值更大,则宝物2拿的数量不能超过LCM / S2,因为若超过,LCM大小的体积部分完全可以替换为宝物1,且价值更大。反之,可以推出宝物2的价值更大的情况
根据这个原理,就可以写出代码了