购买装备(“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛(重现赛))
发布时间: 2017年7月9日 20:20 时间限制: 1000ms 内存限制: 128M
最近盛大的一款游戏传奇世界极其火爆。游戏玩家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
输入数据量较大,建议使用scanf/printf
【分析】
很容易想到一点就是,按装备价格升序排序,从最小的开始买,就可以确定答案装备可以买ans件。
所以在这个的基础上,问题就是怎么提高最低属性值,所以这里用二分找作为最低属性值的装备,check这件装备的属性值作为最低属性值是否满足能买ans件装备的条件
最后输出答案就好了...
//比赛的时候真的...太蠢了自己...题目看反了...先读取的价值再读取的属性....后来也没重新看题目..一直在研究自己的思路哪里有问题...QAQ
【代码】
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct xx{
int a,b;
}now1[100100],now2[100100];
bool cmp1(const xx&x,const xx&y)
{
if (x.a==y.a) return x.b>y.b;
return x.a<y.a;
}
bool cmp2(const xx&x,const xx&y)
{
return x.b<y.b;
}
int M,n,m;
int ANS;
int check(int x)
{
int m=M;
int ans=0;
for (int i=0;i<n&&m>=now1[i].a&&ans<=ANS;i++)
if (now1[i].b>=x)
ans++,m-=now1[i].a;
if (ans>=ANS) return 1;
else return 0;
}
int main()
{
int pp;scanf("%d",&pp);
while (pp--)
{
scanf("%d%d",&n,&m);M=m;
for (int i=0;i<n;i++) scanf("%d%d",&now1[i].b,&now1[i].a),now2[i]=now1[i];
sort(now1,now1+n,cmp1);
sort(now2,now2+n,cmp2);
ANS=0;
for (int i=0;i<n&&m>=now1[i].a;i++) ANS++,m-=now1[i].a;
printf("%d ",ANS);
int l=0,r=n-1,mid;
int xx=now2[0].b;
while (l<=r)
{
mid=(l+r)>>1;
if (check(now2[mid].b)) xx=now2[mid].b,l=mid+1;
else r=mid-1;
}
printf("%d\n",xx);
}
return 0;
}