SHU OJ 420 购买装备(假装背包,其实贪心)

最近盛大的一款游戏传奇世界极其火爆。游戏玩家John,想购买游戏中的装备。已知游戏的商店里有 n 件装备,第 i 件装备具有属性值 ai ,购买需要花费 bi 个金币。John想去购买这些装备,但是账号中只有 m 个金币,John是个很贪婪的家伙,他想购买尽可能多的装备。并且在保证购买到最多件装备的情况下,他还想让他所购买的装备当中拥有最小属性值的装备属性值尽可能大

输入测试组数 T ,每组数据第一行输入整数 n ( 1<=n<=100000 )和 m ( 1<=m<=109 ), 接下来有 n 行,第 i 行有两个数 ai bi ( 1<=ai , bi<=10000 ).

对于每组数据,输出两个数字,第一个数字代表John最多可以购买的装备数,第二个数代表在John购买最多件装备的前提下,所购买的装备当中拥有最小属性值的装备的最大属性值(输入数据保证至少可以购买一件装备)

1
2 4
3 2
2 3
1 3

【分析】我们可以用贪心的方法先算出可以购买装备的最大数量,然后再去二分属性值,得到在装备购买数量最大的情况下属性值的最大值


代码:

#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
#define mst(a,b) memset((a),(b),sizeof(a))  
#define f(i,a,b) for(int i=(a);i<=(b);++i)  
#define rush() int T;scanf("%d",&T);while(T--)  
  
typedef long long ll;  
const int maxn= 100005;  
const ll mod = 1e9+7;  
const int INF = 0x3f3f3f3f;  
const double eps = 1e-6;  
  
struct node  
{  
    int w,cost;  
}a[maxn];  
  
int n,m;  
int num;  
  
bool cmp(const node &a,const node &b)  
{  
    if(a.cost==b.cost)  
        return a.w>b.w;  
    return a.cost<b.cost;  
}  
  
int judge(int x)  
{  
    int sum=0;  
    int Count=0;  
    for(int i=0;i<n;i++)  
    {  
        if(a[i].w>=x)  
        {  
            Count++;  
            sum+=a[i].cost;  
        }  
        if(Count==num)  
            break;  
    }  
    if(Count!=num) return 0;  
    if(sum<=m) return 1;  
    return 0;  
}  
  
int main()  
{  
    rush()  
    {  
        scanf("%d%d",&n,&m);  
        int temp=m;  
        int Min=INF;  
        int Max=0;  
        for(int i=0;i<n;i++)  
        {  
            scanf("%d%d",&a[i].w,&a[i].cost);  
            Min=min(a[i].w,Min);  
            Max=max(a[i].w,Max);  
        }  
        sort(a,a+n,cmp);  
        num=0;  
        while(m>=a[num].cost)    //得到可以购买装备的最大数目  
        {  
            m-=a[num].cost;  
            num++;  
            if(num==n)  
                break;  
        }  
        m=temp;  
        int l=Min,r=Max;  
        int ans;  
        while(l<=r)             //二分属性值区间  
        {  
            int mid=(l+r)/2;  
            if(judge(mid))      //判断是否存在这个属性值,能取到num件装备,且总花费小于总的金币数  
            {  
                ans=mid;  
                l=mid+1;  
            }  
            else r=mid-1;  
        }  
        printf("%d %d\n",num,ans);  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值