bzoj3709: [PA2014]Bohater(貪心)

Hanks_o發表於2018-04-07

題目傳送門

解法:
怪物有加血有扣血的。
分情況討論:
首先先將加血的先打完。
那麼加血的按照怪物消耗的血量從小到大排序。
反正都是加血。肯定先打消耗血量小的啊。

打完之後打扣血的怪物。
要知道最後一個怪物打完其實不需要吃它的草藥了。
也就是說最後一個怪物的草藥應該希望儘量小。
樣例就是一個很好的說明。
所以扣血的怪物按照草藥補的多少從大到小排序。

中間判斷一下即可。

程式碼實現:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
struct node {int d,a,id;}a[110000],b[110000];
bool cmp(node n1,node n2) {return n1.d<n2.d;}
bool cmp1(node n1,node n2) {return n1.a>n2.a;}
int main() {
    int n;ll z;scanf("%d%lld",&n,&z);int len=0,sum=0;
    for(int i=1;i<=n;i++) {
        int x,y;scanf("%d%d",&x,&y);
        if(y>=x) {a[++len].d=x;a[len].a=y;a[len].id=i;}
        else {b[++sum].d=x;b[sum].a=y;b[sum].id=i;}
    }
    sort(a+1,a+1+len,cmp); 
    for(int i=1;i<=len;i++) {
        if(z<=a[i].d) {printf("NIE\n");return 0;}
        z=z-a[i].d+a[i].a;
    }
    sort(b+1,b+1+sum,cmp1);
    for(int i=1;i<=sum;i++) {
        if(z<=b[i].d) {printf("NIE\n");return 0;}
        z=z-b[i].d+b[i].a;
    }
    printf("TAK\n");
    for(int i=1;i<=len;i++)printf("%d ",a[i].id);
    for(int i=1;i<=sum;i++)printf("%d ",b[i].id);
    printf("\n");
    return 0;
}