zoukankan      html  css  js  c++  java
  • [BZOJ3709][PA2014]Bohater

    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
     

     
     
    最优的情况我们肯定先把所有打了可以回血的怪全刷了。
    所以按怪的消耗排序,如果它可以加血,就打它。
    然后加血的处理完了我们该考虑如何应对打了还减血的怪。
    不充钱不可能的
    因为怎么打都减血,并且最后的血量是一定的。
    所以可以倒过来想,发现正好和上面的问题相反...
    你最初有一个确定的血量,把加血想象成扣血,扣血想象成加血, 那么就和第一问一样了。
    所以仿照第一问按照减血从小到大排序,反过来就变成了按加血从大打到小。
     

     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <queue>
    using namespace std;
    inline int read(){
        int res=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
        return res;
    }
    #define int long long
    int n, hp;
    struct date{
        int x, y, c, id;
    }p[100005];
    
    inline bool cmp(date a, date b)
    {
        return a.x < b.x;
    }
    
    inline bool cmp2(date a, date b)
    {
        return a.y > b.y;
    }
    
    bool use[100005];
    int road[100005], top;
    
    signed main()
    {
        n = read(), hp = read();
        for (int i = 1 ; i <= n ; i ++)
        {
            p[i].x = read(), p[i].y = read();
            p[i].c = p[i].y - p[i].x;p[i].id = i;
        }
        sort(p + 1, p + 1 + n, cmp);
        for (int i = 1 ; i <= n ; i ++)
        {
            if (p[i].x >= hp) return puts("NIE"), 0;
            else if (p[i].c >= 0) hp += p[i].c, use[p[i].id] = 1, road[++top] = p[i].id;
        }
        if (top == n)
        {
            puts("TAK");
            for (int i = 1 ; i <= n ; i ++) printf("%lld ", road[i]);
            return 0;        
        }
        sort(p + 1, p + 1 + n, cmp2);
        for (int i = 1 ; i <= n ; i ++)
        {
            if (use[p[i].id]) continue;
            if (hp - p[i].x <= 0) return puts("NIE"), 0;
            else hp += p[i].c, road[++top] = p[i].id;
        }
        puts("TAK");
        for (int i = 1 ; i <= n ; i ++) printf("%lld ", road[i]);
        return 0;    
        return 0;
    }
  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/BriMon/p/9419588.html
Copyright © 2011-2022 走看看