hdu 4544 湫湫系列故事——消灭兔子

原题: http://acm.hdu.edu.cn/showproblem.php?pid=4544

//hdu 4544
//思路:为每一只兔子找能够杀死自己并且花费Q币最少的箭,关键在于不要超时,详细过程: 
//     每一只兔子按血量从大到小排序,每一把箭按攻击值从大到小排序。接下来for循环,为每一只兔子找箭,
//     遍历每一只兔子,查找攻击值大于兔子血量的箭,把这些箭的Q币压入优先队列
//     能够杀死上一只兔子的箭一定能杀死下一只兔子,因为兔子的血量是从大到小排列的,把箭都压进队列后,
//     每次取优先队列的头(即Q币最小)的箭即可,但如果队列为空,表示没有一把剑能杀死当前的兔子,则跳出循环,输出No,有则继续遍历,直到遍历完所有的兔子。 
//优先队列可以,multiset也可以,使用队列要注意自己重写一个cmp,用greater<int>会报编译错误。
//数据可能达到100亿,用long long 
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm> 
using namespace std;
typedef long long ll; 
int rab[100001];
struct J
{
	int di;
	int pi;
}j[100001];
int cmp1(int a,int b)//按血量从大到小排序 
{
	return a>b;
}
int cmp2(J a,J b)//按伤害值由大到小排序 
{
	return a.di>b.di;
}
struct cmp   //队列要用到的cmp结构体 
{
	bool operator ()(int a,int b)
	{
		return a>b;
	}
};
int main()
{
	int n,m;
	while(~scanf("%d %d",&n,&m))
	{
		for(int i=0;i<n;i++)
		{
			scanf("%d",&rab[i]);//兔子 
		}
		for(int i=0;i<m;i++)//箭 
		{
			scanf("%d",&j[i].di);
		}
		for(int i=0;i<m;i++)
		{
			scanf("%d",&j[i].pi);
		}
		if(n>m){//兔子数目大于箭的数目,不能杀死全部兔子 
			printf("No\n");
			continue;
		} 
		sort(rab,rab+n,cmp1); //排好序 
		sort(j,j+m,cmp2);
		priority_queue<int,vector<int>,cmp>q1;//存放q币优先队列,由小到大 
		int k=0; //箭的下标 
		ll money=0;
		int flag=1;//是否能够消灭全部兔子,flag=1能,flag=0不能 
		for(int i=0;i<n;i++)//遍历每一只兔子 
		{
			int di=rab[i];//当前兔子的血量 
			for(;k<m;k++)
			{
				if(j[k].di>=di)//找那些可以杀死兔子的,把q币压入队列 
				{
					q1.push(j[k].pi);
				}else{
					break;
				}
			}
			if(q1.size()==0){//如果没有一支箭可以杀死这只兔子,flag=0,提前结束循环 
				flag=0;
				break;
			}else{
				money=money+q1.top();
				q1.pop();
			}
		} 
		if(flag){ //可以杀死全部兔子 
			printf("%lld\n",money);
		}else{  //不能杀死全部兔子 
			printf("No\n");
		}
	} 
	return 0;
}   //AC
有一道类似的题可以巩固加深 : http://acm.hdu.edu.cn/showproblem.php?pid=4864

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值