[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"<<"
"
#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;
}
原文地址:https://www.cnblogs.com/yangchengcheng/p/15367851.html