定义:
优先级队列相当于一个个容器,里面放着一些元素,也许有很多特征,假设有一个key值,优先级队列就是比较key值来排优先级的。其底层是靠堆来实现的。基本结构如下:
priority_queue <typename> name
读者若不理解,我来举个例子:
假设有三种水果,名称,编号,价钱都不一样。我们希望价格越高的优先级越高。
A B C
node 3 2 1//编号
price 4 5 6//价格
//那么在优先级队列中,C的优先级最高
//在这个例子中,price就是定义中的key值
性质:
一.常用函数
1.top()
堆顶(队首),优先级最高 O(1)时间获得队首
跟queue的front是不一样的,别记错了
2.pop()
弹掉堆顶元素(队首元素)
3.empty()
检测队列是否为空,是空的返回true,否则返回false
4.push()
将x入队
5.size()
返回元素个数
二.设置
int型,double型,char型可以直接使用数据类型,优先级队列对他们的优先级设置一般是数字大的优先级高,char是字典序最大。
下面看个例子:
priority_queue<int> q;
priority_queue<int vector<int>,less<int> >q;
//这两种写法的优先级是一样的
//less<int> 表示数字大的优先级越大,而greater<int> 表示数字小的优先级越大
//其实这也很好理解,越来越小和越来越大嘛
//double和char同上
三.排序
还是以上文的水果为例
struct fruit
{
string name;
int price;
};
价格越高,优先级越高,排序有以下三种写法:
struct fruit
{
string name;
int price;
bool operator < (const fruit &x) const
{
return price<x.price;
}
};
struct fruit
{
string name;
int price;
friend bool operator < (fruit a,fruit b)//friend为友元
{
return a.price<b.price;
}
};
这两种都是通过重载<的(其实从数学上来说,a>b等价于判断a<b)
注意,不要重载>,不然会出错的
如果你想改写成价格越低,优先级越大
那就把
a.price<b.price
//改成
a.price>b.price
发现没?优先级队列的排序似乎跟sort中的cmp是反的呀?
其实也是可以换成cmp的写法,写在外面
struct cmp
{
bool operator() (fruit a,fruit b)
{
return a.price<b.price;
}
};
priority_queue<fruit,vector<fruit>,cmp> q;
//但要这样定义优先级队列,价格越高,优先级越高
友情提醒:struct的;不要丢掉,const和&可以提高效率
思想应用
看一到小例题:
某国正在进行大选,需要在城市中设置投票点来统计票数
现在有N(<=1000)个城市,共有M个投票点(<=5000)需要被放置到这些城市中,每个城市都至少有一个投票点。每个城市的选民被平均分配到这个城市的各个投票点。为了让统计票数时出错的概率最低,因此要使被分配到选民人数最多的投票点的选民人数越少越好,输出所有投票点中分配到最多选民的人数。
分析:
贪心策略
首先,先给每一个城市安排一个投票点,找出每个投票点分配到的选民人数最多的一个城市,然后多给这个城市一个投票点。以此类推,分配完剩下的所有投票点。具体实现时,采用优先级队列的思想,key值为该城市的每个投票点分配到的选民数。
当然看到最大值最小,二分答案一样可以解决。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
int num;//投票点个数
int p;//选民人数
}a[50010];
int n,m,cnt;//cnt可以理解成城市
int main()
{
cnt=1;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i].p;
a[cnt].num=1;
}
m-=n;//每个城市先一个投票点
for(int i=1;i<=m;i++)
{
cnt=1;
for(int j=2;j<=n;j++)
{
if((ll)a[cnt].p*(ll)a[j].num<(ll)a[cnt].num*(ll)a[j].p)
//可以这样理解 :a[cnt].p/a[cnt].num<a[j].p/a[j].num 把人平均分配到投票点中
//避免浮点数,采用乘法
cnt=j;
a[cnt].num++;//其实是j这个城市多了一个投票点
}
}
cnt=1;
for(int i=2;i<=n;i++)//找到最多的那一个
{
if((ll)a[cnt].p*(ll)a[i].num<(ll)a[cnt].num*(ll)a[i].p)
cnt=i;
}
int ans=a[cnt].p/a[cnt].num;
if(a[cnt].p%a[cnt].num!=0) ans++;
cout<<ans;
return 0;
}
PS:但这程序始终有问题
输入:
4 6
120
2680
3400
200
应该输出1700
但却输出1340
求救!!!!