bzoj 3709: [PA2014]Bohater

3709: [PA2014]Bohater

連接

http://www.lydsy.com/JudgeOnline/problem.php?id=3709php

題面

在一款電腦遊戲中,你須要戰勝n只怪物(從1到n編號)。爲了戰勝第i只怪物,你須要消耗d[i]點生命值,但怪物死後會掉落血藥,使你恢復a[i]點生命值。任什麼時候候你的生命值都不能降到0(或0如下)。請問是否存在一種打怪順序,使得你能夠打完這n只怪物而不死掉c++

Input

第一行兩個整數n,z(1<=n,z<=100000),分別表示怪物的數量和你的初始生命值。
接下來n行,每行兩個整數d[i],aispa

Output

第一行爲TAK(是)或NIE(否),表示是否存在這樣的順序。
若是第一行爲TAK,則第二行爲空格隔開的1~n的排列,表示合法的順序。若是答案有不少,你能夠輸出其中任意一個。code

Sample Input

3 5遊戲

3 1get

4 8input

8 3it

Sample Output

TAKclass

2 3 1數據

題解

看到數據範圍,其實就不像是個dp,應該就是貪心。
把怪物分紅兩種怪物,第一種是回覆>傷害的,咱們按照傷害從低到高去打就是最優的。
第二種是傷害>回覆的。咱們打完全部怪物的時候,血量必定是固定的,因此咱們先把把回血多的先殺掉,再殺回血少的。

代碼

#include<bits/stdc++.h>
using namespace std;

vector<pair<pair<int,int>,int> >p1,p2;
vector<int> ans;
bool cmp1(pair<pair<int,int>,int> A,pair<pair<int,int>,int> B){
    return A.first.first<B.first.first;
}
bool cmp2(pair<pair<int,int>,int> A,pair<pair<int,int>,int> B){
    return A.first.second<B.first.second;
}

int main(){
    int n;
    long long z;
    scanf("%d%lld",&n,&z);
    for(int i=1;i<=n;i++){
        pair<pair<int,int>,int> x;
        scanf("%d%d",&x.first.first,&x.first.second);
        x.second = i;
        if(x.first.first>=x.first.second){
            p1.push_back(x);
        }else{
            p2.push_back(x);
        }
    }
    sort(p1.begin(),p1.end(),cmp1);
    for(int i=0;i<p1.size();i++){
        if(z<=p1[i].first.first){
            cout<<"NIE"<<endl;
            return 0;
        }else{
            z-=p1[i].first.first;
            z+=p1[i].first.second;
            ans.push_back(p1[i].second);
        }
    }
    sort(p2.begin(),p2.end(),cmp2);
    for(int i=p2.size()-1;i>=0;i--){
        if(z<=p2[i].first.first){
            cout<<"NIE"<<endl;
            return 0;
        }else{
            z-=p2[i].first.first;
            z+=p2[i].first.second;
            ans.push_back(p2[i].second);
        }
    }
    cout<<"TAK"<<endl;
    for(int i=0;i<ans.size();i++){
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}
相關文章
相關標籤/搜索