贪心+优先队列

最佳工厂
湫湫系列故事——消灭兔子
对于这两道题需要使用贪心+优先队列的方法来做。

首先介绍一下优先队列:优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素
每个元素的优先级根据问题的要求而定。当从优先级队列中删除一个元素时,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。

优先队列的声明:
priority_queue<结构类型> 队列名;
如果默认的话,是less排序。

优先队列使用方法:
q.size();//返回q里元素个数
q.empty();//返回q是否为空,空则返回1,否则返回0
q.push(k);//在q的末尾插入k
q.pop();//删掉q的第一个元素
q.top();//返回q的第一个元素
q.back();//返回q的末尾元素

如果对于队列里元素是一个结构体类型,按照某一个属性排序,就需要对比较函数进行重载,定义优先级的时候,直接在类中写个friend 的操作符重载函数即可:
struct node
{
int d;
int p;
friend bool operator < (node x,node y)
{
return x.p>y.p;
}
};
这个就是重载了小于号

return x.p>y.p;

这行代码表示如果使用优先队列。则会按p从小到大排序,p值小的在队头

湫湫系列故事——消灭兔子
代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct node
{
	int d;//伤害
	int p;//价钱 
	friend bool operator < (node x,node y)
	{
		return x.p>y.p;//价钱低的在队头  
	}
};
int cmp(int x,int y)
{
	return x>y;
} 
int cmp0(node x,node y)
{
	return x.d>y.d;
 } 
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		int blood[100005];
		int flag[100005];
		node s[100005];
		memset(flag,0,sizeof(flag));
		memset(blood,0,sizeof(blood));
		memset(s,0,sizeof(s));
		for(int i=0;i<n;i++)//兔子血量 
		{
			cin>>blood[i];
		}
		for(int i=0;i<m;i++)//伤害 
		{
			cin>>s[i].d;
		}
		for(int i=0;i<m;i++)//价钱 
		{
			cin>>s[i].p;
		}
		sort(blood,blood+n,cmp);//兔子血量递减排序
		sort(s,s+m,cmp0);//箭的伤害递减排序 
		priority_queue <node> q;
		node temp;
		long long sum=0;
		int f=1; //标记有兔子无法消灭 
		int t=0;//作为箭的下标入队 
		if(m<n)
		{
			cout<<"No"<<endl;
		}else
		{
			for(int i=0;i<n;i++)
			{
				while(t<m&&s[t].d>=blood[i])
				{
					q.push(s[t]);
					t++;	
				}
				if(q.empty())
				{
					f=0;
					break;
				}else
				{
					temp=q.top();
					sum+=temp.p;
					q.pop();
				}							
			}
			if(f)
			{
				cout<<sum<<endl;
			}else
			{
				cout<<"No"<<endl;
			}		
			
		}
	}

	return 0;
 }

最佳工厂
代码:

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
struct arr{
	int w;//重量
	int t;//时间 
	friend bool operator <(arr q,arr e)
    {
        return q.w<e.w;//重量大的优先出队 
    }
}a[1001],uu;
int cmp(arr x,arr y)
{
	return x.t<y.t;
}
int main()
{
	int n;
	while(cin>>n)
	{
		for(int i=0;i<n;i++)
		{
			cin>>a[i].w>>a[i].t;
		}
		sort(a,a+n,cmp);//按时间升序 
		int sumt=0;
		int weight=0;//记录总质量 
		priority_queue<arr>s;
		for(int i=0;i<n;i++)
		{
			weight+=a[i].w;
			s.push(a[i]);
			if(weight>a[i].t)
			{
				while(!s.empty()&&weight>a[i].t)
				{
					uu=s.top();
					s.pop();
					weight-=uu.w;					
				}
			}
		 } 
		cout<<s.size()<<endl;
	}
	return 0;	
}
Dijkstra算法是解决单源最短路径问题的一种经典算法,其基本思想是利用贪心的思想,每次选取未确定最短路径的节点中距离起点最近的节点,然后根据该节点更新与该节点相邻的节点的距离。具体实现可以采用邻接表或邻接矩阵来表示图,同时利用优先队列STL来维护节点距离的更新。 算法步骤如下: 1.初始化:将起点的距离设置为0,其余节点的距离设置为无穷大,将所有节点标记为未确定最短路径。 2.选择当前距离起点最近的未确定最短路径节点,将其标记为确定最短路径,并更新其相邻节点的距离。 3.重复步骤2直到终点被标记为确定最短路径或者所有节点均被标记为确定最短路径。 4.输出最短路径。 使用邻接表可以较为简便地实现Dijkstra算法,具体实现如下: ```c++ #include<bits/stdc++.h> using namespace std; const int MAXN=100010; const int INF=0x3f3f3f3f; struct Edge{ int to,w; }; vector<Edge> G[MAXN]; int dis[MAXN]; bool vis[MAXN]; void dijkstra(int s){ priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q; memset(dis,INF,sizeof(dis)); memset(vis,false,sizeof(vis)); dis[s]=0; q.push(make_pair(0,s)); while(!q.empty()){ int u=q.top().second; q.pop(); if(vis[u]) continue; vis[u]=true; for(int i=0;i<G[u].size();i++){ int v=G[u][i].to; int w=G[u][i].w; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; q.push(make_pair(dis[v],v)); } } } } int main(){ int n,m,s,t; scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back((Edge){v,w}); G[v].push_back((Edge){u,w}); } dijkstra(s); printf("%d\n",dis[t]); return 0; } ``` 其中,邻接表G[u]表示节点u的相邻节点,Edge结构体表示边的信息,dis[u]表示起点到节点u的最短路径长度,vis[u]表示节点u是否被标记为确定最短路径。使用优先队列STL来维护节点距离的更新,pair<int,int>表示节点距离和节点编号,greater<pair<int,int>>表示节点距离的比较器,使得距离小的节点在队列前面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值