• [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;
    }
  • 相关阅读:
    hdu 2211(约瑟夫环问题)
    hdu 3605(二分图的多重匹配 | 网络流)
    hdu 3360(经典二分匹配)
    hdu 2255(KM)
    ajax无翻页刷新简单实例2
    在Updatepanel中使用Response.Redirect
    asp.net 使用UpdatePanel 返回服务器处理后弹出对话框
    再记一个SQL分页存储过程
    DIV中图片垂直居中
    在Repeter中用RadioButton生成单选按钮组的实现
  • 原文地址:https://www.cnblogs.com/BriMon/p/9419588.html
Copyright © 2020-2023  润新知