优先队列 (结构体自定义比较)(重载函数)

之前一直在 用 sort 的结构体自定义函数,感觉到 STL 强大,今天刷题遇见优先队列 的题 ,要求跟 以前一样,数据量大,要求对某个信息排序,并且 做相应的 操作,如果用 普通的结构体来模拟 ,但是这个sort 要每次插进结构体数组,都要排序一遍,耗时很大,不如用一个 优先队列,和重载函数,插进去一个,就会自动的去排序,不用再一遍一遍的 去 sort 排序。

如何用重载函数?(由于能力有限)

1.直接上代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<queue>
typedef struct node
{
	int num;
	friend bool operator < (struct node a,struct node b) 
	{
		return a.num>b.num;
	}
}point;

这个 friend bool operator 好像只能在 结构体里面 使用,并且 后面 的参数 要两个,写一个 会报错。

 把 那个 struct 改为 const ,也是对的,

2.

#include<stdio.h>
#include<iostream>
using namespace std;
#include<queue>
typedef struct node
{
	int num;
	bool operator < (const node& b) const 
	{
		return num>b.num;
	}
}point;

用 bool operator ,就需要 在后面 加上一个 const ,在结构体里面,后面的 参数 只能是一个。

3.

#include<stdio.h>
#include<iostream>
using namespace std;
#include<queue>
typedef struct node
{
	int num;
	
}point;

bool operator < (const node& a,const node & b) 
{
	return a.num>b.num;
}

或者直接  就可以。

bool operator < (point a,point b)

以上的都是,题目要求有很多的元素变量的时候我们使用结构体会简单一些,当只有一个的时候,我们不采用这种做法,直接用以下的方法会更简单一些:

greater<int> less<int>
priority_queue<int,vector<int>,greater<int> >s;



//如果对于需要排列的元素有特殊的排序要求,就可以自己写出排序函数来 
priority_queue<int, vector<int>, cmp>s;
struct cmp
{
	bool operator()(const int &a,const int &b)
	{
		return a>b;	
	}	
};



如果是一个结构体作为优先队列的元素的话,我们可以写一个结构体进行排序。

#include<iostream>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<algorithm>

using namespace std;
typedef pair<int, int> p;

struct node
{
	string name;
	int score;
	node(string name1, int now)
	{
		name = name1;
		score = now;
	}
	bool operator<(const node& a)const
	{
		if (score != a.score)
			return score < a.score;
		return name > a.name;
	}
};

int main()
{
	priority_queue<node>s;
	s.push(node("ts", 123));
	s.push(node("ww", 100));
	s.push(node("lp", 100));

	while (!s.empty())
	{
		cout << s.top().name << ' ' << s.top().score << endl;
		s.pop();
	}
	return 0;
}


来看看题:

题面:看病要排队 HDU - 1873

看病要排队这个是地球人都知道的常识。
不过经过细心的0068的观察,他发现了医院里排队还是有讲究的。0068所去的医院有三个医生(汗,这么少)同时看病。而看病的人病情有轻重,所以不能根据简单的先来先服务的原则。所以医院对每种病情规定了10种不同的优先级。级别为10的优先权最高,级别为1的优先权最低。医生在看病时,则会在他的队伍里面选择一个优先权最高的人进行诊治。如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。

现在就请你帮助医院模拟这个看病过程。

Input

输入数据包含多组测试,请处理到文件结束。
每组数据第一行有一个正整数N(0<N<2000)表示发生事件的数目。
接下来有N行分别表示发生的事件。
一共有两种事件:
1:"IN A B",表示有一个拥有优先级B的病人要求医生A诊治。(0<A<=3,0<B<=10)
2:"OUT A",表示医生A进行了一次诊治,诊治完毕后,病人出院。(0<A<=3)

Output

对于每个"OUT A"事件,请在一行里面输出被诊治人的编号ID。如果该事件时无病人需要诊治,则输出"EMPTY"。
诊治人的编号ID的定义为:在一组测试中,"IN A B"事件发生第K次时,进来的病人ID即为K。从1开始编号。

Sample Input

7
IN 1 1
IN 1 2
OUT 1
OUT 2
IN 2 1
OUT 2
OUT 1
2
IN 1 1
OUT 1

Sample Output

2
EMPTY
3
1
1

这道题 就需要 用到优先队列(可以用三个优先队列),(也可以用一个队列数组),我用的是队列数组。

如果优先级不同,就按优先级从高到低 来看病,如果不是 ,就按来的先后 来看病,典型的 优先队列(重载来做)

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn = 2001;
struct node
{
	int jishu;
	int k;
	bool operator<(const node &b) const
        {
                if ( jishu == b.jishu)
                        return k > b.k;
                return jishu < b.jishu;
        }
};

int main()
{
	int i;
	char zhiling[maxn];
	int n;
	while (cin >> n)
	{
		priority_queue<node>s[maxn];
		int count = 1;
		while (n--)
		{
			memset(zhiling, 0, sizeof(zhiling));
			cin >> zhiling;
			if (zhiling[0] == 'I')
			{
				struct node q;
				q.k = count++;
				int ysnum;
				cin >> ysnum >> q.jishu;
				s[ysnum].push(q);
			}
			else
			{
				int ysnum2;
				cin >> ysnum2;
				if (s[ysnum2].size() == 0)
					cout << "EMPTY" << endl;
				else
				{
					cout << s[ysnum2].top().k << endl;
					s[ysnum2].pop();
				}
			}
		}
		
	}
	return 0;
}

一开始 没有按照 先来的顺序,就WA 了好几发。

2.Windows Message Queue HDU - 1509

题面:

消息队列是Windows系统的基本基础。对于每个进程,系统都维护一个消息队列。如果此过程发生某些事情,例如鼠标单击,文本更改,系统将向队列添加消息。同时,如果该队列不为空,则该进程将根据优先级值从队列中获取消息。请注意,优先级较低的值意味着较高的优先级。在此问题中,系统会要求您模拟消息队列,以便将消息放入消息队列并从消息队列中获取消息。
输入
输入中只有一个测试用例。每一行都是一个命令,“GET”或“PUT”,这意味着获取消息或发送消息。如果命令是“PUT”,则只有一个字符串表示消息名称,两个整数表示参数和优先级后跟。最多将有60000个命令。请注意,一条消息可以出现两次或更多次,如果两条消息具有相同的优先级,则首先处理一条消息(即,具有相同优先级的FIFO)。处理到文件结尾。
输出
对于每个“GET”命令,输出从消息队列中获取的命令,其中名称和参数在一行中。如果队列中没有消息,则输出“EMPTY QUEUE!”。 “PUT”命令没有输出。

Sample Input

GET
PUT msg1 10 5
PUT msg2 10 4
GET
GET
GET

Sample Output

EMPTY QUEUE!
msg2 10
msg1 10
EMPTY QUEUE!

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<queue>
const int maxn=60005;
using namespace std;
typedef struct node
{
	char zifu[20];
	int num;
	int ji;
	int id; 
	bool operator < (const node& b) const  
	{
		if(ji!=b.ji)
			return ji>b.ji;
		return id>b.id;
	}  
}point;





char zhiling[maxn];


int main()
{
	priority_queue<point>s;
	int i=0;
	int count=1;
	while(cin>>zhiling)
	{
		if(zhiling[0]=='G')
			{
				if(!s.empty())
					{
						point q;
						q=s.top();
						s.pop();
						cout<<q.zifu<<' '<<q.num<<endl;
					}
				else
					cout<<"EMPTY QUEUE!"<<endl;
			}
		else
		{
			point zhilinga;
			zhilinga.id=count++;
			cin>>zhilinga.zifu>>zhilinga.num>>zhilinga.ji;
			s.push(zhilinga);
		}	
		
			
	}	
	return 0;
}

也是对优先级的考虑。

3.Stones  HDU - 1896

题面 :

因为自行车的位置不对,塞姆普开始每天早上从东到西步行,每天晚上步行回来。散步会引起疲劳,所以这次塞姆普总是在路上玩一些游戏。
路上有很多石头,当他遇到一块石头时,如果碰到的是第奇数个的石头,他会尽可能地把它扔到前面;如果碰到的是第偶数个的石头,他会把它留在原处。现在给您一些关于路上石头的信息,您要告诉我从起点到塞姆普路过的最远石头的距离。请注意,如果两个或更多的石头停留在同一位置,您将首先遇到较大的(具有最小Di的,如输入中所述)。

Input

在第一行中,有一个整数T(1<=T<=10),它表示输入文件中的测试用例。
然后是T个测试用例。对于每个测试用例,我将在第一行中给出整数N (0<=N<=100000),这意味着路上的石头数量。然后是N行,行中有两个整数Pi(0<=Pi<=100000)和Di(0<=Di<=1000),这意味着第i个石头的位置以及塞姆普可以把它扔多远。

Output

个测试用例输出一行,如描述所述。

Sample Input

2
2
1 5
2 4
2
1 5
6 6

Sample Output

11
12

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn=100005;
typedef struct node
{
	int weizhi;
	int di;
	bool operator < (const node& b )const
	{
		if(weizhi==b.weizhi)
			return di>b.di;
		return weizhi>b.weizhi;	
	}
	
}point;
priority_queue<point>s;

int main()
{
	int i=0;
	int t;
	cin>>t;
	int tonenum;
	while(t--)
	{
		i=0;
		cin>>tonenum;
		for(i=0;i<tonenum;i++)
			{
				point p;
				cin>>p.weizhi>>p.di;
				s.push(p);
			}
			int bushu=1;
			int maxjuli=0;
		while(!s.empty())
			{
				if(bushu%2!=0)
					{
						bushu=!bushu;
						point q;
						q=s.top();
						s.pop();
						i=q.weizhi;
						q.weizhi+=q.di;
						s.push(q);
						maxjuli=q.weizhi;	
					}
				else
				{
					i=s.top().weizhi;
					s.pop();
					bushu=!bushu;
				}
			}
	
		cout<<maxjuli<<endl;
	}
		
		
	return 0;
}

先是 把所有的 石头的位置 和优先级 插入优先度列。

在这里 ,每遇见 一个 石头 ,就要判断 这个石头 是否是偶数次,如果是,那就把它从优先队列中弹出,如果不是,就把他扔后位置 更新插入优先队列 。因为是自动排序的,所以只要控制好奇数和偶数就行,我用了个开关0和1,不断取非,就能 集合偶相互转化,什么时候 是结束呢?那就是 优先队列 里面 没有元素的时候,就 结束了,题目说的是,不能再 经过 奇数 石头。那怎么 来计算 最大的距离,每次扔石头时,就用maxjuli来记录位置,这个题,真是有点意思,就是 你扔的 没有 队列里面 后面一个远, 下次 走到 这个 石头时(这时就是偶数),就把他弹出。如果扔的比队列后面一个元素的位置远,走到下一个时,(因为他这是偶数)所以直接弹出。如果后面 没有元素了,那这个 就是最远的;如果还有元素,就把下面一个 扔的位置,在记录下来,最后的结束是空队列,所以说,最后一个 扔的是最远的。

看看 图解

应该就是这样 。

加油 。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值