題解:看到這個題第一反應肯定是完全揹包,但是由於袋子的容量1e8(太大,數組存不下),所以不能直接用完全揹包,用貪心的話是不正確的(如果把性價比最大的貪完,揹包容量可能還有剩餘,此時用剩餘的部分去裝蘋果,則這部分裝入的蘋果性價比可能較低,導致它的價值小於去掉一個性價比最高的加上一個性價比較高的),所以就有了分段求值,在揹包容量大於(1e3或1e4或1e5或1e6)用貪心,小於或等於(1e3或1e4或1e5或1e6)用完全揹包。
Description
以前,有個神祕的院子裏面有三種蘋果,每個蘋果的數量是無限的。有一個小姑娘帶了一個大袋子來到院子,她從來沒見過這麼多的蘋果。每種蘋果都有大小以及出售的價格,小姑娘想獲得最大的利潤,但是她不知道怎麼才能做到。於是她來向你尋求幫助,你能告訴她能獲得的最大價值嗎?
Input
第一行一個整數T(T <= 50),表示測試數據的組數。
每組測試數據有四行組成,前三行每行有兩個整數S和P,分別表示每種蘋果的大小(1 <= S <= 100)和價格(1 <= P <= 10000)
第四行有一個整數V(1 <= V <= 100,000,000)表示小姑娘袋子的大小。
Output
每組測試數據輸出組數和小姑娘能得到的最大的價值。
Sample Input
1 1 1 2 1 3 1 6
Sample Output
Case 1: 6
代碼:
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
long long int f[1005];
struct apple{
int w;
int v;
double p;
}s[4];
bool cmp(struct apple x,struct apple y)
{
return x.p>y.p;
}
int main()
{
int T, l = 0;
long long int V;
cin>>T;
while(T--)
{
l++;
memset(f,0,sizeof(f));
for(int i = 1; i <= 3; i++)
{
cin>>s[i].w>>s[i].v;
s[i].p = double(s[i].v)/double(s[i].w);
}
sort(s+1,s+4,cmp);
cin>>V;
long long int ans = 0;
if(V > 1000)//貪心
{
long long int k = V - 1000;
ans += (k / s[1].w + 1) * s[1].v;
V = V - (k / s[1].w + 1) * s[1].w;
}
if(V <= 1000)//完全揹包
{
for(int i = 1; i <= 3; i++)
for(int j = s[i].w; j <= V; j++)
f[j] = max(f[j], f[j-s[i].w] + s[i].v);
ans += f[V];
}
cout<<"Case "<<l<<": "<<ans<<endl;
}
return 0;
}