Description
在一款电脑游戏中,你需要打败n只怪物(从1到n编号)。为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值。任何时候你的生命值都不能降到0(或0以下)。请问是否存在一种打怪顺序,使得你可以打完这n只怪物而不死掉
Input
第一行两个整数n,z(1<=n,z<=100000),分别表示怪物的数量和你的初始生命值。
接下来n行,每行两个整数d[i],a[i](0<=d[i],a[i]<=100000)
Output
第一行为TAK(是)或NIE(否),表示是否存在这样的顺序。
如果第一行为TAK,则第二行为空格隔开的1~n的排列,表示合法的顺序。如果答案有很多,你可以输出其中任意一个。
Sample Input
3 5
3 1
4 8
8 3
3 1
4 8
8 3
Sample Output
TAK
2 3 1
2 3 1
贪心
首先。打了能加血的肯定要先干掉。因为是加血所以我们尽量满足消耗的限定就行,所以我们把这部分加血的d[i]从小到大排序然后顺次消灭
对于打了减血的,我们反过来考虑。消耗和回复反过来看,那就和上面一种情况一样了。把回复降序排序就好。
如果消耗等于回复。那随便放在上面两种情况的任意一种都可以。
最后。。记得开longlong。因为10^5*10^5=10^10>2147483647
#include<cstdio>
#include<algorithm>
using namespace std;
struct npc
{
long long d,g;
int x;
long long xx;
}a[100001];
inline bool cmp1(npc x,npc y)
{
if(x.xx<y.xx)
return true;
return false;
}
inline bool cmp2(npc x,npc y)
{
if(x.d<y.d)
return true;
return false;
}
inline bool cmp3(npc x,npc y)
{
if(x.g>y.g)
return true;
return false;
}
int main()
{
int n;
long long z;
scanf("%d%lld",&n,&z);
int i;
for(i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].d,&a[i].g);
a[i].x=i;
a[i].xx=a[i].d-a[i].g;
}
sort(a+1,a+1+n,cmp1);
int td=0;
for(i=1;i<=n;i++)
if(a[i].g-a[i].d<=0)
break;
i--;
sort(a+1,a+1+i,cmp2);
td=i;
for(i=td;i<=n;i++)
if(a[i].g-a[i].d<0)
break;
if(i<=n)
sort(a+i,a+1+n,cmp3);
int s=0;
for(i=1;i<=n;i++)
{
if(z<=a[i].d)
{
printf("NIE\n");
return 0;
}
z=z+a[i].g-a[i].d;
}
printf("TAK\n");
printf("%d",a[1].x);
for(i=2;i<=n;i++)
printf(" %d",a[i].x);
printf("\n");
return 0;
}