您的位置:首页 > Web前端

The 2014 ACM-ICPC Asia Shanghai Regional Contest - I - Defeat the Enemy (贪心+multiset)UVALive - 7146

2017-09-28 19:14 465 查看
题意:

交战双方,我方n只军队,敌方m只军队,每只军队都有生命值和攻击力。两军交战,本身生命值减去对方的攻击力,若剩余生命值小于等于0那么阵亡。若我军能消灭敌军,最多生还多少队伍?不能的话,输出-1。

思路:

贪心做法,先将我方军队按攻击力升序,敌方军队按生命值升序。用multiset维护我方军队的生命值,加入multiset中的军队,倘若其攻击力都能消灭敌方的当前和以后的队伍。对于敌方的一只军队,找到我方中,能消灭他的,且不被他消灭的最小生命值,倘若不存在,则牺牲multiset中最小的那个值(田忌赛马的感觉)。

ps:

这里的multiset利用迭代器就行操作,因为删除元素时不像set那样,比如{1,1,2}中想要删除1,那么最后的结果是{2},而不是{1,2}。

代码:

#include<iostream>
#include<algorithm>
#include<set>
#include<cstdio>
using namespace std;

struct troop
{
int harm,life;
}w[100010],d[100010];

bool cmp1(troop a,troop b)//攻击力排序
{
return a.harm>b.harm;
}

bool cmp2(troop a,troop b)//生命值排序
{
return a.life>b.life;
}

int main()
{
int t,cnt,n,m,p=0;
bool flag;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
printf("Case #%d: ",i);
scanf("%d%d",&n,&m);
for(int j=0;j<n;j++)
scanf("%d%d",&w[j].harm,&w[j].life);
for(int j=0;j<m;j++)
scanf("%d%d",&d[j].harm,&d[j].life);

if(n<m)//如果我方军队数量小于敌方,直接输出-1
{
printf("-1\n");
continue;
}

sort(w,w+n,cmp1);
sort(d,d+m,cmp2);
multiset <int> defense;
p=cnt=0;//cnt记录阵亡的人数
flag=true;
for(int j=0;j<m;j++)
{
for(int k=p;k<n;k++)
{
//能消灭敌方军队军队的生命值加入multiset
if(w[k].harm>=d[j].life)
{
defense.insert(w[k].life);
p++;
}
else break;
}
//如果我方剩余军队不能消灭敌方队伍退出
if(defense.empty())
{
flag=false;
break;
}
else
{
//能不损失军队,则用我方生命值恰好高于敌方的去消灭
//倘若必须损失军队,则损失当前生命值最低的
multiset <int> ::iterator it;
it=defense.upper_bound(d[j].harm);
if(it!=defense.end())
defense.erase(it);
else
{
defense.erase(defense.begin());
cnt++;
}
}
}
if(!flag)
printf("-1\n");
else
printf("%d\n",n-cnt);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐