Description
Once ago, there is a mystery yard which only produces three kinds of apples. The number of each kind is infinite. A girl carrying a big bag comes into the yard. She is so surprised because she has never seen so many apples before. Each kind of apple has a size and a price to be sold. Now the little girl wants to gain more profits, but she does not know how. So she asks you for help, and tell she the most profits she can gain.
Input
In the first line there is an integer T (T <= 50), indicates the number of test cases.
In each case, there are four lines. In the first three lines, there are two integers S and P in each line, which indicates the size (1 <= S <= 100) and the price (1 <= P <= 10000) of this kind of apple.
In the fourth line there is an integer V,(1 <= V <= 100,000,000)indicates the volume of the girl's bag.
Output
For each case, first output the case number then follow the most profits she can gain.
Sample Input
1 1 1 2 1 3 1 6
Sample Output
Case 1: 6
一共有三种不同类型的苹果分别有不同的重量和价值,每种类型的苹果有无限个,给你一个篮子的重量,问能获得的最大价值是多少。
读了一遍题觉得这是个完全背包的模板题,但是再一看,V的重量最大是1e8,数组太大开不到。那就考虑在大范围内用贪心的方法,小范围内用完全背包。重量过大时,找到一个性价比最高的类型,一直装到可以用背包解决这个问题(可以用背包解决问题的临界值在代码中给出)。
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL long long
#define inf 0x3f3f3f3f
#define eps 1e-8
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
const double PI=acos(-1.0);
using namespace std;
const int maxn=1000000;
long long f[maxn*2];
struct node
{
int s,p;
double pi;
};
node ss[5];
bool cmp(node a,node b)//按价值从大到小排序
{
return a.pi>b.pi;
}
void pack(long long v)//完全背包
{
memset(f,0,sizeof(f));
for(int i=0;i<3;i++)
{
for(int j=ss[i].s;j<=v;j++)
{
f[j]=max(f[j],f[j-ss[i].s]+ss[i].p);
}
}
}
int main()
{
int t;
scanf("%d",&t);
int cnt=1;
while(t--)
{
long long ans=0;
long long v;
for(int i=0;i<3;i++)
{
scanf("%d%d",&ss[i].s,&ss[i].p);
ss[i].pi=ss[i].p*1.0/ss[i].s;
}
scanf("%lld",&v);
if(v<=maxn)//如果重量不是很大,直接用背包解决
{
pack(v);
printf("Case %d: ",cnt++);
cout<<f[v]<<endl;
}
else
{
sort(ss,ss+3,cmp);
long long n=v-maxn;//需要用贪心解决的重量
ans+=n/ss[0].s*ss[0].p;//排序过后s[0]性价比最高,全部乘ss[0]
v=maxn+n%ss[0].s;//因为n除以ss[0]不一定是整数,所以现在的重量要加上n除以ss[0]剩下的那些
pack(v);//再用背包解决
printf("Case %d: ",cnt++);
cout<<ans+f[v]<<endl;
}
}
}