[PA2014]Bohater
题意:
需要打败 \(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"<<"\n"
#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\n");
for(int i = 1; i <= n; i++)
printf("%lld ", b[i].id);
//fclose(stdin);
//fclose(stdout);
return 0;
}