优先队列专题 poj 2431 2442 3190 1442 3614
来源:互联网 发布:python google earth 编辑:程序博客网 时间:2024/05/18 12:33
优先队列:
一种灵活的数据结构,经常和贪心算法结合使用,并且比较适合于动态的相关算法。
POJ2431
题意:有n个加油站,给出含有的油的量和与目的地的距离,每单位油能走每单位的距离,判断是否能走完全路程,如果能走完给出,需要的最少的加油站的数目;
模拟题,但是需要使用优先队列(最大值),模拟每次经过加油站都把油加入优先队列之中。如果路上没有油了,就取出优先队列中的最大值“使用”,进行模拟但是需要注意各种边界条件。
struct Node{ int len; int has; Node(int i,int j):len(i),has(j){}};bool operator<(const Node&n1,const Node&n2){return n1.has<n2.has;}struct cmp2{ bool operator ()(int &a,int &b){ return a<b;//最大值优先 }};
注意:对于一个节点,规定了<号,那么是最大值优先(默认)
默认的int也是最大值优先
最小值优先
priority_queue<int,vector<int>,greater<int>> p;
POJ2442
题意:给出m行每行有n个数,每行选择一个数,理论上有m^n种选择方法,求出这些方法中和最小的n个。
1.将第一序列读入data1向量中,并按升序排序。
2.将数据读入data2向量中,并按升序排序。
将data2[0] + data1[i] ( 0<=i<=n-1)读入dataq向量中
用make_heap对dataq建堆。
然后data2[1] + data1[i] (0<=i<=n-1),如果data2[1] + data1[i]比堆dataq的顶点大,则退出,否则删除
堆的顶点,插入data2[1] + data1[i]。然后是data2[2],…data2[n - 1]
3.将dataq的数据拷贝到data1中,并对data1按升序排序
4.循环2,3步,直到所有数据读入完毕。
5.打印data1中的数据即为结果。
#include<stdio.h>#include<iostream>#include<algorithm>#define N 2000+7using namespace std;int n,m;int a[N];int b[N];int aid[N];int main(){ //freopen("D://in.txt","r",stdin); int cases; scanf("%d",&cases); while(cases--){ scanf("%d%d",&m,&n); if(m==1){ for(int i=0;i<n;i++){ scanf("%d",&a[i]); } sort(a,a+n); }else{ for(int lines=0;lines<m;lines++){ if(lines==0){ for(int i=0;i<n;i++){ scanf("%d",&a[i]); } sort(a,a+n); }else{ for(int i=0;i<n;i++){ scanf("%d",&b[i]); } sort(b,b+n); for(int i=0;i<n;i++){ aid[i]=b[0]+a[i]; } make_heap(aid,aid+n); for(int i=1;i<n;i++){ for(int j=0;j<n;j++){ int tmp=b[i]+a[j]; if(tmp<aid[0]){ pop_heap(aid,aid+n); aid[n-1]=tmp; push_heap(aid,aid+n); } } } for(int i=0;i<n;i++){ a[i]=aid[i]; } sort(a,a+n); } } } for(int i=0;i<n;i++){ cout<<a[i]<<" "; }cout<<endl; }}
思路很重要;为什么不直接在原来的a上建堆,而是又开辟了辅助数组aid:因为比较堆顶元素和a[i]+b[j]的时候会因为a数组的元素改变产生错误。
相当于一个逐渐替换的过程,首先全部选择的是第一个元素,然后分别用后面的替换原来堆中最大的。
POJ3190
题意:
每头牛的挤奶时间是【a,b】需要占用一个工具,如何安排牛的挤奶时间,让需要的工具最少。
维护一个优先队列(小),是每个区间的结束时间;
对月每一头牛的开始时间,如果比堆顶的时间还要早说明,需要一个工具,否则的话,更新这个堆顶的时间为这头牛的结束时间。
统计堆的大小,就是需要的工具个数
POJ1442
题意:
动态的添加元素和查询
第一次查询是第1小的元素,第二次查询是第二小的元素……
代码
放入元素的代码
minHeap.push ( array[k] ); if ( ! maxHeap.empty() && minHeap.top() < maxHeap.top() ){ t1 = minHeap.top(); minHeap.pop(); t2 = maxHeap.top(); maxHeap.pop(); maxHeap.push(t1); minHeap.push(t2); }
第i次查找第i大的元素,因此,只要保证两个堆的大小是动态变化的即可
每次查找的元素都在小顶堆的堆顶,用完之后,将其放入大顶堆
printf("%d\n",minHeap.top()); maxHeap.push ( minHeap.top() ); minHeap.pop();
POJ3614
题意:奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光。现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i。求最多满足多少头奶牛
可以直接贪心
int n,m;struct Node{ int b,e; Node(int b,int e):b(b),e(e){} Node(){}};struct SPF{ int val,num; SPF(int val,int num):val(val),num(num){} SPF(){}};bool cmp(const Node&n1,const Node&n2){ if(n1.b<n2.b)return true; else if(n1.b>n2.b)return false; else return n1.e>n2.e;}bool cmp2(const SPF&n1,const SPF&n2){return n1.val<n2.val;}Node a[N];int mark[N];SPF b[N];int main(){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++){scanf("%d%d",&a[i].b,&a[i].e);} for(int i=0;i<m;i++){scanf("%d%d",&b[i].val,&b[i].num);} sort(a,a+n,cmp); sort(b,b+m,cmp2); for(int i=0;i<m;i++){//对于每一个给定的防晒霜的值 for(int num=0;num<b[i].num;num++){//对于每一个防晒霜的数量 int index=-1; int miner=INF; for(int k=0;k<n&&a[k].b<=b[i].val;k++){ if(mark[k]==0&&a[k].e>=b[i].val){ if(a[k].e<miner){ miner=a[k].e; index=k; } } } mark[index]=1; } } int sum=0; for(int i=0;i<n;i++){sum+=mark[i];} cout<<sum<<endl;}
显然有更好的解决方案:
对于满足题意的奶牛,可以让其按照区间右端点的最小值优先进入优先队列,然后不断的从队列中出来ni个数,ni是当前防晒霜的数量。
- 优先队列专题 poj 2431 2442 3190 1442 3614
- 优先队列 POJ 3614
- POJ 2442 优先队列
- POJ 2442 优先队列
- POJ 1442 优先队列
- poj 1442 优先队列
- 优先队列专题
- POJ 3614 Sunscreen 优先队列
- POJ 3614 Sunscreen 优先队列
- POJ 3614 Sunscreen 优先队列
- POJ 3614 Sunscreen 优先队列
- POJ 2442 Sequence(优先队列)
- poj 3190 优先队列+贪心
- POJ 3190 贪心+优先队列
- poj-2431 贪心+优先队列
- poj 2431 优先队列&贪心
- poj 2431 Expedition(优先队列)
- poj 2431 Expedition 【优先队列】
- UVa 572 Oil Deposits
- Maven3 --- Eclipse集成Maven
- 九度 1010
- CentOS运行C++出现内存错误——double free or coruption
- 组合数
- 优先队列专题 poj 2431 2442 3190 1442 3614
- WHOJ 1606 - Funny Sheep【水】
- 抽奖系统数据库设计
- 使用Google浏览器必备的插件
- 虚拟机Vmware上安装Ubuntu操作系统,如何配置Vmware tools
- 欢迎使用CSDN-markdown编辑器
- 神经单元
- myeclipse如何修改Web项目名称
- android中对输入手机号码有效性验证(是否为正确的手机号码)