bzoj3709:[PA2014]Bohater

题目描述

在一款电脑游戏中,你需要打败n只怪物(从1到n编号)。为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值。任何时候你的生命值都不能降到0(或0以下)。请问是否存在一种打怪顺序,使得你可以打完这n只怪物而不死掉

输入

第一行两个整数n,z(1<=n,z<=100000),分别表示怪物的数量和你的初始生命值。
接下来n行,每行两个整数d[i],a[i](0<=d[i],a[i]<=100000)

输出

第一行为TAK(是)或NIE(否),表示是否存在这样的顺序。
如果第一行为TAK,则第二行为空格隔开的1~n的排列,表示合法的顺序。如果答案有很多,你可以输出其中任意一个。

样例输入

3 5
3 1
4 8
8 3

样例输出

TAK
2 3 1
 
题解
分成三种怪物,打完加血,不加不减,打完减血。
贪心可知,先打加血的,再打不加不减,最后打减血怪。
加血怪先打减血少的,减血怪先打加血多的。
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define maxn 100005
 5 using namespace std;
 6 struct fuck{int a,d,x;}add[maxn],take[maxn],com[maxn];
 7 bool cmp1(fuck p,fuck q){return p.d<q.d;}
 8 bool cmp2(fuck p,fuck q){return p.a>q.a;}
 9 int n,cnt,tcnt,acnt;
10 long long z;
11 int main()
12 {
13     int d,a;
14     scanf("%d%lld",&n,&z);
15     for(int i=1 ; i<=n ; ++i )
16         {
17             scanf("%d%d",&d,&a);
18             if(a-d>0){add[++acnt].d=d;add[acnt].a=a;add[acnt].x=i;}
19             else if(a-d<0){take[++tcnt].d=d;take[tcnt].a=a;take[tcnt].x=i;}
20             else{com[++cnt].d=d;com[cnt].a=a;com[cnt].x=i;}
21         }
22     sort(add+1,add+1+acnt,cmp1);
23     sort(take+1,take+1+tcnt,cmp2);
24     for(int i=1 ; i<=acnt ; ++i )
25         if(z-add[i].d<=0){printf("NIE");return 0;}
26         else z=z-add[i].d+add[i].a;
27     for(int i=1 ; i<=cnt ; ++i )if(z-com[i].d<=0){printf("NIE");return 0;}
28     for(int i=1 ; i<=tcnt ; ++i )
29         if(z-take[i].d<=0){printf("NIE");return 0;}
30         else z=z-take[i].d+take[i].a;
31     printf("TAK
");
32     for(int i=1 ; i<=acnt ; ++i)printf("%d ",add[i].x);
33     for(int i=1 ; i<=cnt ; ++i)printf("%d ",com[i].x);
34     for(int i=1 ; i<=tcnt ; ++i)printf("%d ",take[i].x);
35     return 0;
36 } 
 
原文地址:https://www.cnblogs.com/fujudge/p/7496809.html