【BZOJ-3709】Bohater 贪心

3709: [PA2014]Bohater

Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 835  Solved: 274
[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

Sample Output

TAK
2 3 1

HINT

Source

鸣谢Jcvb

Solution

看见BeiYu坐旁边他刚A,打开看题,看完问:"这不贪心的排个序,随随便便就能A?",BeiYu....

然后开始写贪心,写残了一个贪心TAT

正确的贪心策略其实也很好想,考虑计算出打每个怪的血量净变化量

首先当  差值   全都为正时,按  伤害  从小到大排(可以防止回血很多,但同时伤害爆炸,可以秒你的情况)

然后差值为正的一定贪心的排在差值为负的前面,否则可以按照   回血量  从大到小排序

这里的差值是指:回复量-伤害量

Attention: 自己的血量要开longlong

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
long long read()
{
    long long 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;
}
#define maxn 100010
int n; long long z;
struct MonsterNode
{
    int d,a,c,id;
    bool operator < (const MonsterNode & A) const
        {
            if (c>=0 && A.c>=0) return d<A.d;
            if (c*A.c<=0) return c>=0;
            return a>A.a;
        }
}mo[maxn];
int main()
{
    n=read(),z=read();
    for (int i=1; i<=n; i++) mo[i].d=read(),mo[i].a=read(),mo[i].c=mo[i].a-mo[i].d,mo[i].id=i;
    sort(mo+1,mo+n+1);
//    for (int i=1; i<=n; i++) printf("%d %d %d\n",mo[i].d,mo[i].a,mo[i].c);
    for (int i=1; i<=n; i++)
        if (z>mo[i].d) z+=mo[i].c; else {puts("NIE"); return 0;}
    puts("TAK");
    for (int i=1; i<=n; i++) printf("%d ",mo[i].id); puts("");
    return 0;
} 

 

posted @ 2016-05-27 07:05  DaD3zZ  阅读(268)  评论(0编辑  收藏  举报