csuoj1640机智的刷题方式(背包)

Description

小B想参加中南大学2015年大学生程序设计竞赛暑期集训,相信猛刷自然强的小B表示做题进集训队完全不是事~当然刷题还是有一定技巧的,考虑到每种题的分值不一样,难度不一样,小B要在上面做一些权衡。分数与题目对应关系如下:

入门题
1分/题
基础题
2分/题
进阶题
5分/题

首先,小B希望自己能尽快确保自己入选集训队,已知他做每种题目的时间,还需要H分来达到入队要求,请问他最快能在多长时间内达到要求?
然后,小B想试着挑战一下自己的极限。已知他在接下来的时间里还有X的时间拿来刷题,那么他最多能刷到多少分?

Input

多组数据,第一行有一个整数T,表示有T组数据。(T<=100)
以下每组数据第一行有三个整数A,B,C,表示小B做 入门题 基础题 进阶题 要花的时间的数量。(1<=A、B、C<=100)
然后第二行是2个整数H,X,分别表示小B还需要的分数和接下来小B拿来刷题的时间。(1<=H、X<=10000)

Output

每组数据输出两行,第一行输出小B刷够H分最少所需时间。第二行输出小B可能刷到的最高分数。

Sample Input

4
1 2 5
3 10
1 2 3
4 10
1 2 4
3 7
2 3 4
3 7

Sample Output

3
10
3
16
3
8
4
7


这个题是有坑的,需要H分达到入队要求,但并不是说刚好H分,超过H分也是可以的呀,同理时间X不一定要用完就可以达到能取得的最大分数

所以我们可以把第一个H背包开大一点,然后求出最小时间

第二个X背包可以在i<5的范围内搜索最大值

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
int a[10020];
int main()
{
	int T;
	scanf("%d",&T);
	int w[3];
	int v[3]={1,2,5};
	int h,x;
	while (T--)
	{
	    scanf("%d%d%d",&w[0],&w[1],&w[2]);
	    scanf("%d%d",&h,&x);
	    memset(a,0,sizeof a);
	    for(int i=h-1+5;i>0;i--)   //开了一个大小适度的背包(大小为H+5,这里j从H-1+5开始是因为空间剩余H+5的背包是不装东西的)
            for(int j=0;j<3;j++)
            if(a[i]==0)a[i]=a[i+v[j]]+w[j];
            else a[i]=min(a[i],a[i+v[j]]+w[j]);
        int minn=10000000;
        for(int i=1;i<=5;i++)          //搜索的时候从最大的(H+5)背包装完的情况到最小的(H)背包装完的情况中搜索
            if(a[i]!=0)minn=min(a[i],minn);
        printf("%d\n",minn);
        memset(a,0,sizeof a);
        for(int i=x;i>=0;i--)
            for(int j=0;j<3;j++)
            if(i+w[j]<=x)
            a[i]=max(a[i],a[i+w[j]]+v[j]);
        int maxx=-1;
        for(int i=0;i<6;i++)
            maxx=max(a[i],maxx);
        printf("%d\n",maxx);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值