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;
}