Codeforces 611E 贪心 STL

Codeforces 611E
题目链接:
http://codeforces.com/contest/611/problem/E
题意:
给n(200000)只怪物的生命值,然后三个英雄的攻击力。
英雄可以合力打败一只怪物,按回合执行,每个回合英雄最多打败一只怪物。
问最少几个回合打败所有怪物。
不能打败所有怪物输出-1.
思路:
标解不是这样的,因为讨论比较多个人比较倾向下面的这种写法。
确定一个优先级。
对于一个分组,如果它能打败的怪物的最大值大优先;打败怪物个数多优先;打败怪物生命值总和大优先。
至于为什么是这样:
1)因为总要打败生命值最大的怪物,所以每次优先打败怪物生命值最大的一组。
2)因为要优先输出分组数小的答案,所以一个分组里的怪物越多越好。
3)前两者相同时,为了避免出现例如a+b < Life[i] && c > Life[i]时,导致下一组分组中可以攻击怪物的数量变少的情况,所以优先攻击怪物生命值总和大的一组。
然后就枚举分组情况,每次取最优的分组就可以。

实现用STL,比较麻烦可以研究下。
源码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <iterator>
using namespace std;
const int MAXN = 200000 + 5;
int quality[5], vis[MAXN];
bool cmp1(int a, int b){return a > b;}
vector<int>Kill, MaxKill;
multiset<int>cost;
multiset<int>::iterator it, it2;
int main()
{
//    freopen("611E.in", "r", stdin);
    int n;
    while(scanf("%d", &n) != EOF){
        cost.clear();
        for(int i = 0 ; i < 3 ; i++)    scanf("%d", &quality[i]);
        int u;
        for(int i = 0 ; i < n ; i++)    scanf("%d", &u), cost.insert(u);
        int ans = 0;
        int ok = 0;
        while((int)cost.size() > 0){
            int MaxKillNum = 0;
            int MaxKillSum = 0;
            int MaxKillCost = 0;
            MaxKill.clear();
            ok = 0;
            for(int j = 0 ; j < (1 << 3) ; j++){
                Kill.clear();
                int KillNum = 0;
                int KillSum = 0;
                int KillCost = 0;
                for(int k = 0 ; k < 3 ; k++){
                    if(j & (1 << k)){
                        KillCost += quality[k];
                    }
                    else{
                        it2 = cost.upper_bound(quality[k]);
                        if(it2 != cost.begin()){
                            it2--;
                            Kill.push_back(*it2);
                            KillNum++;
                            KillSum += *it2;
                            cost.erase(it2);
                        }
                    }
                }
                if(j){
                    it2 = cost.upper_bound(KillCost);
                    if(it2 != cost.begin()){
                        it2--;
                        Kill.push_back(*it2);
                        KillNum++;
                        KillSum += *it2;
                        KillCost = *it2;
                        cost.erase(it2);
                    }
                    else    KillCost = 0;
                }
                for(int k = 0 ; k < (int)Kill.size() ; k++)
                    KillCost = max(KillCost, Kill[k]);
                int flag = 0;
                if(KillCost > MaxKillCost)  flag = 1;
                else if(KillCost == MaxKillCost && KillNum > MaxKillNum)    flag = 1;
                else if(KillCost == MaxKillCost && KillNum == MaxKillNum && KillSum > MaxKillSum)   flag = 1;
//                printf("j = %d, KillCost = %d, KillNum = %d, KillSum = %d, flag = %d\n", j, KillCost, KillNum, KillSum, flag);
                if(flag){
                    MaxKillCost = KillCost;
                    MaxKillNum = KillNum;
                    MaxKillSum = KillSum;
                    MaxKill.clear();
                    for(int k = 0 ; k < (int)Kill.size() ; k++){
                        MaxKill.push_back(Kill[k]);
                    }
                    ok = 1;
                }
                for(int k = 0 ; k < (int)Kill.size() ; k++){
                    cost.insert(Kill[k]);
                }
            }
//                printf("ans = %d, ok = %d\n", ans, ok);
//            printf("ans = %d, ", ans);
            if(ok){
                ans++;
                for(int k = 0 ; k < (int)MaxKill.size() ; k++){
//                        printf("MaxKill[%d] = %d\n", k, MaxKill[k]);
                    it2 = cost.upper_bound(MaxKill[k]);
                    it2--;
//                    printf("%d ", MaxKill[k]);
                    cost.erase(it2);
                }
//                printf("\n");
            }
            else    break;
//                printf("cost.size() = %d\n", cost.size());
//                system("pause");
        }
        if(ok)  printf("%d\n", ans);
        else    printf("-1\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值