BZOJ 3709: [PA2014]Bohater
3709: [PA2014]Bohater
Time Limit: 5 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1050 Solved: 352
[Submit][Status][Discuss]
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
HINT
Source
贪心,对于怪兽可以分成两类——
一类,打完之后血量不降反升,这些怪兽按照消耗血量从小到大排序;
一类,打完之后血量不升反降,这些怪兽按照恢复血量从大到小排序。
且血量上升怪一定排在血量下降怪前面。
易知这种打怪顺序是最优的,检测是否可行即可。
1 #include <bits/stdc++.h> 2 3 typedef long long longint; 4 5 struct Monster { 6 int a, b, id; 7 Monster(void) {} 8 Monster(int _a, int _b, int _id) { 9 a = _a, b = _b, id = _id; 10 } 11 } 12 mon1[200000], 13 mon2[200000]; 14 15 bool cmp1(const Monster &a, const Monster &b) { 16 return a.a < b.a; 17 } 18 19 bool cmp2(const Monster &a, const Monster &b) { 20 return a.b > b.b; 21 } 22 23 int n; 24 longint h; 25 int tot1, tot2; 26 27 signed main(void) { 28 scanf("%d%lld", &n, &h); 29 30 for (int i = 1, a, b; i <= n; ++i) { 31 scanf("%d%d", &a, &b); 32 if (a < b) 33 mon1[tot1++] = Monster(a, b, i); 34 else 35 mon2[tot2++] = Monster(a, b, i); 36 } 37 38 std::sort(mon1, mon1 + tot1, cmp1); 39 std::sort(mon2, mon2 + tot2, cmp2); 40 41 for (int i = 0; i < tot1; ++i) { 42 if (h <= mon1[i].a) 43 return puts("NIE"), 0; 44 h -= mon1[i].a; 45 h += mon1[i].b; 46 } 47 48 for (int i = 0; i < tot2; ++i) { 49 if (h <= mon2[i].a) 50 return puts("NIE"), 0; 51 h -= mon2[i].a; 52 h += mon2[i].b; 53 } 54 55 puts("TAK"); 56 57 for (int i = 0; i < tot1; ++i) 58 printf("%d ", mon1[i].id); 59 for (int i = 0; i < tot2; ++i) 60 printf("%d ", mon2[i].id); 61 62 return puts(""), 0; 63 }
@Auhtor: YouSiki