您的位置:首页 > 其它

UVA - 12325 Zombie's Treasure Chest : 分类枚举 思维题

2017-07-26 20:43 381 查看

题目点此跳转

Some brave warriors come to a lost village. They are very lucky and find a lot of treasures and a big treasure chest, but with angry zombies.

 The warriors are so brave that they decide to defeat the zombies and then bring all the treasures back. A brutal long-drawn-out battle lasts from morning to night and the warriors find the zombies are undead and invincible.

 Of course, the treasures should not be left here. Unfortunately, the warriors cannot carry all the treasures by the treasure chest due to the limitation of the capacity of the chest. Indeed, there are only two types of treasures: emerald and sapphire. All of the emeralds are equal in size and value, and with infinite quantities. So are sapphires.

 Being the priest of the warriors with the magic artifact: computer, and given the size of the chest, the value and size of each types of gem, you should compute the maximum value of treasures our warriors could bring back.

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.

Sample Input

2

100 1 1 2 2

100 34 34 5 3

Sample Output

Case #1: 100

Case #2: 86

思路

 题目意思是你有一个体积为N的箱子和两种数量无限的宝物。宝物1的体积为S1,价值为V1;宝物2的体积为S2,价值为V2。输入均为32位带符号整数。你的任务是计算最多能装多大价值的宝物。例如,n=100,S1=V1=34,S2=5,V2=3,答案为86,方案是装两个宝物1,再装6个宝物2。每种宝物都必须拿非负整数个。

 (书上原话)最容易想到的方法是:枚举宝物1的个数,然后尽量多拿宝物2。这样做的时间复杂度为O(N/S1),当N和S1相差非常悬殊时效率很低。当然,如果N/S2很小时可以改成枚举宝物2的个数,所以这个方法不奏效的条件是:S1和S2都很小,而N很大。幸运的是,S1和S2都很小时,有另外一种枚举法B:S2个宝物1和S1个宝物2的体积相等,而价值分别为S2*V1和S1*V2。如果前者比较大,则宝物2最多只会拿S1-1个(否则可以把S1个宝物2换成S2个宝物1);如果后者比较大,则宝物1最多只会拿S2-1个。不管是哪种情况,枚举量都只有S1或者S2。

 这样,就得到了一个比较“另类”的分类枚举算法:

 当N/S1比较小时枚举宝物1的个数,时间复杂度为O(N/S1),否则,当N/S2比较小时枚举宝物2的个数,时间复杂度为O(N/S2),否则说明S1和S2都比较小,执行枚举法B,时间复杂度为O(max{S1, S2})。

 本题的关键就是分类讨论以缩小枚举的规模.

代码

#include <algorithm>
#include <iostream>
#include <sstream>
#include <utility>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cstring>
#include <cstdio>
#include <cmath>
#define met(a,b) memset(a, b, sizeof(a));
#define IN freopen("in.txt", "r", stdin);
#define OT freopen("ot.txt", "w", stdout);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5 + 10;
const int INF = 0x7fffffff;
const int dir[5][2] = {0,0,-1,0,1,0,0,-1,0,1};

LL n, s1, v1, s2, v2;

int main() {
#ifdef _LOCAL
IN; //OT;
#endif // _LOCAL

int kase = 0, t; scanf("%d", &t);
while(t--) {
scanf("%lld%lld%lld%lld%lld", &n, &s1, &v1, &s2, &v2);
LL l1 = n/s1, l2 = n/s2;
LL ans = 0;
if(l1 < maxn || l2 < maxn) {
if(l1 <= l2) {
for(int i = 0; i <= l1; ++i) {
LL tmp = i*v1 + (n-i*s1)/s2*v2;
ans = max(ans, tmp);
}
}
else {
for(int i = 0; i <= l2; ++i) {
LL tmp = i*v2 + (n-i*s2)/s1*v1;
ans = max(ans, tmp);
}
}
}
else {
LL t1 = s1*v2, t2 = s2*v1;
if(t1 >= t2) {
for(int i = 0; i <= s2-1; ++i) {
LL tmp = i*v1 + (n-i*s1)/s2*v2;
ans = max(ans, tmp);
}
}
else {
for(int i = 0; i <= s1-1; ++i) {
LL tmp = i*v2 + (n-i*s2)/s1*v1;
ans = max(ans, tmp);
}
}
}
printf("Case #%d: %lld\n", ++kase, ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: