题意:
需要打败 (n) 只怪物(从 1 到 (n) 编号),为了打败第 (i) 只怪物,消耗 (d[i]) 点生命值,但恢复 (a[i]) 点生命值。任何时候你的生命值都不能降到 0(或 0 以下)。
请问是否存在一种打怪顺序,使得你可以打完这 (n) 只怪物而不死掉。
题解:
贪心,先打回血的怪物,再打掉血的怪物。
-
对于(a[i] > d[i]), 也就是回血的怪物,可以按 (d[i]) 从小到大来排序。
-
对于(a[i] < d[i]), 也就是掉血的怪物,可以将最后剩余的血量看做初始血量 (x)( (x) 是固定的), 将怪物的 (a)(增血量)与 (b)(掉血量)进行交换,倒着来看,就与上一种情况一样,倒着是按 (a[i]) 从小到大排序,那么正着是按 (a[i]) 从大到小排序。
一定要开long long!
#include <cstdio>
#include <iostream>
#include <algorithm>
#define orz cout<<"AK IOI"<<"
"
#define int long long
using namespace std;
const int maxn = 1e5 + 10;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
int n, z, ans[maxn];
struct node{
int d, a, id, c;
}b[maxn];
bool cmp(node a, node b)
{
/*if(a.c > 0 && b.c > 0) return a.d < b.d;
if(a.c < 0 && b.c < 0) return a.a > b.a;
return a.c > 0;*/
if(a.c * b.c < 0) return a.c > 0;
if(a.c < 0) return a.a > b.a;
return a.d < b.d;
}
signed main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n = read(), z = read();
for(int i = 1; i <= n; i++)
{
b[i].d = read(), b[i].a = read(), b[i].id = i;
b[i].c = b[i].a - b[i].d;
}
sort(b + 1, b + n + 1, cmp);
for(int i = 1; i <= n; i++)
{
z -= b[i].d;
if(z <= 0) { printf("NIE"); return 0;}
z += b[i].a;
}
printf("TAK
");
for(int i = 1; i <= n; i++)
printf("%lld ", b[i].id);
//fclose(stdin);
//fclose(stdout);
return 0;
}