一开始以为是动规,后来发现不是,算是贪心吧。
思路:输入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; }