一开始以为是动规,后来发现不是,算是贪心吧。
思路:输入N,S1,V1,S2,V2,分别代表背包总容量,一号宝藏的体积和价格,二号宝藏的体积和价格。
那么 N / S1 和 N / S2 可以分别代表 N容量最多能装 一号,二号宝藏的数量,那么如果这2个数其中一个比较小的时候,如果N / S1 小 直接枚举一号宝藏的数量 进行 二号宝藏数量的计算,反之亦然。
但是还存在一个比较特殊的情况:如果N / S1 和 N / S2 都很大呢? 也就是说S1,S2都很小。
我们不妨假设下表:
宝藏一 | 宝藏二 | |
单位体积 | S1 | S2 |
单位价格 | V1 | V2 |
数量 | S2 | S1 |
总价格 | S2*V1 | S1*V2 |
总体积 | S1*S2 | S1*S2 |
我们不妨设一号宝藏有S2个,二号宝藏有S1个,那么一号宝藏总体积和二号宝藏总体积就一样了,如果S2 *V1 > S1 * V2的话,说明宝藏二的数量肯定在[0,S1)内,因为
如果体积大于了S1,那么,宝藏二的总价格 就为 S * V2(S > S1),那么肯定体积就大于S1*S2了,S1*S2的体积下,拿宝藏二肯定不如拿宝藏一。
以上就是分析,还有一个比较坑人的地方就是由于输入为32位,所以需要使用Long Long 否则会被后台数据卡死的(亲身经历~ TAT)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stack>
#include<queue>
#include<map>
#include<vector>
typedef long long LL;
using namespace std;
LL n,V1,S1,V2,S2;
#define INF 5000
LL solve(int choice){
LL MAX = -1;
if(choice == 0){
for(LL i = 0 ; i * S1 <= n ; i++){
LL temp = n - i * S1;
LL ans = temp / S2 * V2 + i * V1;
MAX = max(MAX,ans);
}
}
else if(choice == 1){
for(LL i = 0 ; i * S2 <= n ; i++){
LL temp = n - i * S2;
LL ans = temp / S1 * V1 + i * V2;
MAX = max(MAX,ans);
}
}
else {
LL Sum1 = S2 * V1;
LL Sum2 = S1 * V2;
if(Sum1 > Sum2){
for(LL i = 0 ; i < S1 ; i++){
LL temp = n - i * S2;
LL ans = temp / S1 * V1 + i * V2;
MAX = max(MAX,ans);
}
}
else {
for(LL i = 0 ; i < S2 ; i++){
LL temp = n - i * S1;
LL ans = temp / S2 * V2 + i * V1;
MAX = max(MAX,ans);
}
}
}
return MAX;
}
int main(){
int T,Case = 1;
scanf("%d",&T);
while(T--){
scanf("%lld%lld%lld%lld%lld",&n,&S1,&V1,&S2,&V2);
/*分别输入宝物一和宝物二的体积 价值*/
LL ans;
if((n / S1) < INF)
ans = solve(0);
else if((n / S2) < INF)
ans = solve(1);
else {
ans = solve(2);
}
printf("Case #%d: %lld\n",Case ++, ans);
}
return 0;
}