Pick apples 贪心+完全背包

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;
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值