HDU4415 Assassin’s Creed 2012ACM/ICPC 杭州赛区网络赛 F

HDU4415(枚举,贪心)

大意:

杀手有把耐久为m的“袖口刀”,一共有n个敌人,每个敌人都有防御值Ai ,杀死一个为Ai的敌人则m -= Ai,每个敌人有“能量刀”,杀死敌人后可以获取敌人的能量刀,能量值Bi是几就可以再杀几个人,刀可以叠加,Bi为0就是这个敌人没有能量刀。问消耗尽量小的m,最多可以杀多少敌人。

题解:

把敌人按照Bi分为a组和b组,a组的敌人都是没有能量刀的敌人(Bi=0),b组的Bi>0。

枚举1、只用袖口刀杀a组里的人,能杀多少是多少,杀完若m还有剩余,则尝试去杀b组的人,若能杀掉一个防御最低的,用得到的能量刀就能把b组的人全杀掉。

 例如数据:

1
5
7 1
7 1
1 0
1 0
1 0

枚举2、仅用袖口刀去杀b组的人,不用能量刀,直到剩余的m值不够用了,在用能量刀接着杀,若能杀完,在用能量刀和袖口刀去杀a组的人

例如数据:

1
6 20
10 2
10 2
100 0
100 0
100 0
100 0

枚举3、用袖口刀杀掉b组防御最低的(杀不掉则回到枚举1),然后用得到的能量刀杀完b组的人,在用袖口刀和能量刀杀a组的人

例如数据:

1
5 5
10 1
4 1
5 2
100 0
1 0

然后比较3种枚举得到的值,得出答案,貌似贪心思想没大用到。。。

#include <iostream>
#include <vector>
#include <algorithm>
#define FOR(a,b) for(int i = (a);i < (b);i ++)
using namespace std;

struct Enemy
{
	int Ai,Bi;
};
bool cmp(const Enemy& a,const Enemy& b)
{
	return a.Ai < b.Ai;
}
struct Ans
{
	int num,cost;
};
bool operator<(const Ans& a,const Ans& b)
{
	if(a.num == b.num) return a.cost > b.cost;
	return a.num < b.num;
}

vector<Enemy> b;
vector<int> a;

Ans afirst(int m)
{
	Ans ans;
	ans.cost = 0,ans.num = 0;	
	for(int i = 0; i < a.size() && m >= a[i];i ++)
	{
		m -= a[i];
		ans.num ++;
		ans.cost += a[i];
	}
	if(!b.empty() && m >= b[0].Ai) ans.num += b.size(),ans.cost += b[0].Ai;
	return ans;
}
Ans bfirst(int m,int energy)
{
	Ans ans;
	ans.num = 0,ans.cost = m;
	for(;ans.num < b.size() && m >= b[ans.num].Ai;ans.num ++) m -= b[ans.num].Ai;
	ans.cost -= m;

	energy -= b.size() - ans.num;
	if(energy >= a.size()) ans.num = a.size()+b.size();
	else{
		ans.num = b.size() + energy;
		for(int i = 0;i <= a.size() - energy && a[i] <= m;i ++) ans.num ++,ans.cost += a[i],m -= a[i];
	}
	return ans;
}
Ans banda(int m,int energy)
{
	Ans ans;
	ans.num = 0,ans.cost = 0;
	ans.cost += b[0].Ai;
	m -= ans.cost;
	energy -= b.size() -1;
	if(energy >= a.size()) ans.num = a.size() + b.size();
	else {
		ans.num = b.size() + energy;
		for(int i = 0;i <= a.size() - energy && a[i] <= m;i ++) ans.num ++,ans.cost += a[i],m -= a[i];
	}
	return ans;
}
int main()
{
	int n,m,num,cost,energy;
	Enemy enemy;
	Ans ans,ans1,ans2,ans3;
	int testcases;
	scanf("%d",&testcases);
	for(int ca = 1; ca <= testcases; ca ++)
	{
		a.clear(),b.clear();
		num = 0,cost = 0;
		energy = 0;
		scanf("%d%d",&n,&m);		
		FOR(0,n)
		{
			scanf("%d%d",&enemy.Ai,&enemy.Bi);
			if(enemy.Bi) b.push_back(enemy),energy += enemy.Bi;
			else a.push_back(enemy.Ai);
		}
		if(!b.empty()) sort(b.begin(),b.end(),cmp);
		if(!a.empty()) sort(a.begin(),a.end());
		
		if(a.empty())//每个敌人都有剑
		{
			if(m >= b[0].Ai) printf("Case %d: %d %d\n",ca,b.size(),b[0].Ai);
			else printf("Case %d: 0 0\n",ca);
			continue;
		}
		//枚举1 只用自己的武器在a中杀人
		ans1 = afirst(m);
		//枚举2 只用自己的武器杀b中的人
		ans2 = bfirst(m,energy);
		//枚举3 杀一个b中的,用敌人的武器搞死完b,然后搞a
		ans3 = banda(m,energy);

		ans = ans1 < ans2 ? ans2 : ans1;
		ans = ans < ans3 ? ans3 : ans;
		printf("Case %d: %d %d\n",ca,ans.num,ans.cost);
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值