[PA2014]Bohater

题意:

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

题解:

贪心,先打回血的怪物,再打掉血的怪物。

  1. 对于\(a[i] > d[i]\), 也就是回血的怪物,可以按 \(d[i]\) 从小到大来排序。

  2. 对于\(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;
}
posted @ 2021-10-05 06:33  _程门立雪  阅读(41)  评论(0编辑  收藏  举报