题目大意:给定容量为v的背包,给定两种无限的物品,重量和价值分别为 s1,v1,s2,v2. 求背包可以容纳的最大的价值。但是输入都是带符号的32位二进制整数。
解题:刚看到题的时候想用背包来解,但是看到数据范围之后,是不可能的。首先,此题只要确定了其中一个物品的数量,则另外一个武平改装多少个也就确定了,所以说此题使用枚举方法。
使用枚举方法时,发现确定一个枚举量,此题肯定会超时。此题的枚举方法值得学习。
考虑到s1,s2都可能很大,或者很小,或者一个大一个小。当一个大一个小的时候,我们枚举大的那个,但是又会出现大的那个就很小。此时我们认为的设定一个上限(程序中设置的是1000000),当要枚举的那个的最大数量大于设定的值时,我们使用另一种枚举方法。另一种枚举方法为:当是s1*v2 < s2*v1时,说明相同的体积(s1*s2)情况下全部装第一种物品的价值最大(可以借用物理上的密度使思想来理解),这样的话,就发现最大枚举量是s1(枚举的是第二个物品的数量).(如果第二个物品的数量大于等于s1,则用另一个物品替代的话,肯定价值更大一些);反之也是一样的情况。
//
// main.cpp
// uva 12325 - Zombie's Treasure Chest
//
// Created by XD on 15/7/29.
// Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
#define ll long long
using namespace std ;
int maxs = 1000000 ;
int main(int argc, const char * argv[]) {
int casenum ;
scanf("%d" ,&casenum) ;
ll n , s1 ,v1,s2,v2 ;
int j = 0 ;
while (casenum--) {
ll asn = 0 ;
scanf("%lld%lld%lld%lld%lld",&n,&s1,&v1,&s2,&v2) ;
if(n / s1 <=maxs)
{
ll t = n / s1 ;
for (int i = 0; i <= t ; i++) {
ll t1 = (n - i * s1 ) / s2 ;
ll tasn = i * v1 + t1 * v2 ;
asn = asn > tasn?asn:tasn ;
}
}
else if(n / s2 <=maxs)
{
ll t = n / s2 ;
for (int i = 0; i <= t ; i++) {
ll t1 = (n - i * s2 ) / s1 ;
ll tasn = i * v2+ t1 * v1 ;
asn = asn > tasn?asn:tasn ;
}
}
else{
if (s1*v2 < s2*v1) {
//枚举s2
for (int i = 0 ;i<s1 ; i++) {
ll t1 = (n - i * s2 ) / s1 ;
ll tasn = i * v2 + t1 * v1 ;
asn = asn > tasn?asn:tasn ;
}
}
else{
for (int i = 0 ;i<s2 ; i++) {
ll t1 = (n - i * s1 ) / s2 ;
ll tasn = i * v1 + t1 * v2 ;
asn = asn > tasn?asn:tasn ;
}
}
}
printf("Case #%d: %lld\n" ,++j , asn ) ;
}
return 0;
}