bzoj 3709 [PA2014]Bohater(贪心)

题意:n个怪,杀每个怪会掉x点血,杀死怪后有个血瓶可以恢复y点血,给定初始血量,问是否可以杀死所有的怪。

思路:这题的思路真是巧妙……首先分成两部分,一部分是杀掉怪可以回血的,另一部分是杀掉怪要掉血的,那么对于可以回血的,显然,先杀那些伤害低的,因为你的血量是一直增加的,所以伤害高的留在后面就好了。至于会掉血的,不妨反过来看,把伤害看做血瓶,把血瓶看做伤害,从最终的状态往回倒流,那么你就会发现,这和第一种是同一个情况了。。。这思路真是厉害,想了半天奇怪的贪心没贪过去Orz


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#include<bitset>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-6
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
struct Node
{
    int x,y,id;
    Node(int x = 0,int y = 0,int id = 0):x(x),y(y),id(id){}
}na[maxn],nb[maxn];
int ans[maxn];
bool vis[maxn];
bool cmp1(Node a,Node b)
{
    return a.x < b.x;
}
bool cmp2(Node a,Node b)
{
    return a.y > b.y;
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n;
    ll hp;
    while(~scanf("%d%lld",&n,&hp))
    {
        int m1 = 0,m2 = 0;
        int x,y;
        for(int i = 1;i <= n;++i)
        {
            scanf("%d%d",&x,&y);
            if(x <= y)
                na[m1++] = Node(x,y,i);
            else
                nb[m2++] = Node(x,y,i);
        }
        sort(na,na + m1,cmp1);
        sort(nb,nb + m2,cmp2);
        memset(vis,0,sizeof(vis));
        int tot = 0;
        for(int i = 0;i < m1;++i)
        {
            if(hp > na[i].x)
            {
                hp += na[i].y - na[i].x;
                ans[tot++] = na[i].id;
            }
            else
                break;
        }
        for(int i = 0;i < m2;++i)
        {
            if(hp > nb[i].x)
            {
                hp += nb[i].y - nb[i].x;
                ans[tot++] = nb[i].id;
            }
            else
                break;
        }
        if(tot != n)
            printf("NIE\n");
        else
        {
            puts("TAK");
            for(int i = 0;i < tot;++i)
            {
                if(i) printf(" ");
                printf("%d",ans[i]);
            }
            puts("");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值