这个贪心有点炸。。
首先能发现,只要能杀一个Bi非零的,则可以根据红利至少杀死所有的Bi非零的
如果不能杀死bi非零的,那么就按ai排序从小到大杀。
如果能杀一个bi的话,
设红利总共sum,如果已经能把所有人杀完,则直接 ans1=n,ans2=0,否则,把其余人按ai排序贪心。
为什么呢?
如果能杀一个Bi非零的,必然是,杀死所有Bi,并获得红利,才是优的,因为每多杀一个Bi,要么红利不变,要么增加,但是问题在于Bi要用红利杀还是用耐久度杀,我们可以这样处理,直接相当于把所有红利到手,然后把除了最小的哪个bi去掉,其他人排序,从小的开始杀,必然合法。
在杀得过程中,我们只需要保证bi全被杀掉即可,而本来红利就》num of bi非零的人数,还用耐久杀了,则保证bi全被杀掉,并且尽可能把耐久度花费小的杀掉
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
struct node
{
int a,b;
};
node tt[100005];
bool cmp(node a,node b)
{
return a.a<b.a;
}
int main()
{
int cnt=1;
int t;
cin>>t;
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
int sumb=0;
int mm=m;
int mini,minb=2e9;
for (int i=1; i<=n; i++)
{
scanf("%d%d",&tt[i].a,&tt[i].b);
if (tt[i].b)
{
sumb+=tt[i].b;
if (tt[i].a<minb)
{
minb=tt[i].a;
mini=i;
}
}
}
int ans1,ans2;
if (m>=minb)
{
if (sumb+1>=n)
{
ans1=n;
ans2=minb;
}
else
{
swap(tt[mini],tt[n]);
sort(tt+1,tt+n,cmp);
m-=minb;
ans1=sumb+1;
for (int i=1; i<n&&ans1<n; i++)
{
if (m>=tt[i].a)
{
ans1++;
m-=tt[i].a;
}
else break;
}
ans2=mm-m;
}
}
int ans3=0,ans4;
m=mm;
sort(tt+1,tt+n+1,cmp);
for (int i=1; i<=n; i++)
{
if (m>=tt[i].a)
{
ans3++;
m-=tt[i].a;
}
else break;
}
ans4=mm-m;
if (ans3>ans1)
{
ans1=ans3;
ans2=ans4;
}
else if (ans3==ans1)
ans2=min(ans2,ans4);
printf("Case %d: %d %d\n",cnt++,ans1,ans2);
}
return 0;
}