uva 11997 K Smallest Sums 优先队列
来源:互联网 发布:十大当红网络女作家 编辑:程序博客网 时间:2024/06/07 04:54
题目:https://uva.onlinejudge.org/external/119/11997.pdf
对于两组数a[n],b[n],每组长度为n,现在要得到a[i]+b[j] (1<=i,j<=n)的和 中前n小的值。
先对b[n]排序
方法是利用b[1] + x<b[2]+x<...<b[n]+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a[n]+b[1]);
弄出n个指针p[i],分别表示队列里a[i]加上的是b[p[i] ];
每次取出队头,删去,然后补上一个新的元素。
比如取出 a[i]+b[p[i] ]
那么得到一个答案a[i]+b[p[i] ],然后放入a[i]+b[p[i] +1];
进行n次,那么可以得到前n小的数
变式:
对于两组数a[n],b[m],现在要得到a[i]+b[j] (1<=i<=n,1<=j<=m)的和 中前k小的值。
先对b[m]排序
方法是利用b[1] + x<b[2]+x<...b[m]+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a[n]+b[1]);
弄出n个指针p[i],分别表示队列里a[i]加上的是b[p[i] ];
每次取出队头,删去,然后补上一个新的元素。
比如取出 a[i]+b[p[i] ]
那么得到一个答案a[i]+b[p[i] ],然后放入a[i]+b[p[i] +1];
进行k次,那么可以得到前k小的数
变式:
有n组数,每组数取一个数相加 得到一个结果,要求前k小的结果分别是多少。
对于每两组数,用到的一定是这两组数中(分别取1个数,他们的 和中)最小的k个数,
故将这两组变成了一组,减少了组数,依此类推,直到最后剩下一组(长度为k)
const int INF =0x3f3f3f3f;const int maxn= 760 ;//const int maxm= ;//by yskysker123int n,a[maxn][maxn];int p[maxn];struct Node{ int num,index; Node(){} Node(int num,int index):num(num),index(index){}};struct cmp{ bool operator()(Node x,Node y ) { return x.num>y.num; }};void merge(int le,int ri){ priority_queue<Node,vector<Node > ,cmp> q; for(int i=1;i<=n;i++) { p[i]=1; q.push( Node( a[le][i]+a[ri][1],i) ); } for(int ii=1;ii<= n ;ii++) { Node tmp=q.top();q.pop(); int index=tmp.index; int num=tmp.num; a[le][ii]=num ; p[index]++; if(p[index]<=n ) q.push(Node (num-a[ri][p[index]-1 ]+a[ri][p[index] ] ,index ) ); }}int main(){ int x; while(~scanf("%d",&n)) //有一种错误叫做忘写~或!=EOF,这种错误常常是由于移动代码时造成的,通常还会在事先 { //表现为 () 内有; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); } sort(a[i]+1,a[i]+1+n); } for(int i=2;i<=n;i++) { merge(1,i ); } for(int i=1;i<n ;i++) printf("%d ",a[1][i]); printf("%d\n",a[1][n]); } return 0;}
#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n) for(int i=0 ;i<(n) ;i++)#define FOR1(i,n) for(int i=1 ;i<=(n) ;i++)#define FORD(i,n) for(int i=(n) ;i>=0 ;i--)#define lson num<<1,le,mid#define rson num<<1|1,mid+1,ri#define MID int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mk make_pair#define _f first#define _s secondusing namespace std;//const int INF= ;typedef long long ll;//const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);
- UVa 11997 K Smallest Sums / 优先队列
- UVA 11997 K Smallest Sums 优先队列
- UVA 11997 K Smallest Sums(优先队列)
- uva 11997 - K Smallest Sums(优先队列)
- UVA 11997 - K Smallest Sums 优先队列
- uva 11997 K Smallest Sums 优先队列
- UVa 11997 K Smallest Sums (优先队列)
- K Smallest Sums uva+优先队列
- UVA 11997 - K Smallest Sums(优先队列+多路合并)
- UVA 11997 K Smallest Sums(优先队列)
- UVA - 11997 K Smallest Sums 归并排序+优先队列
- UVA 11997 K Smallest Sums(优先队列)
- 【优先队列之多路合并】UVA - 11997 K Smallest Sums
- UVA 11997 K Smallest Sums(优先队列)
- K Smallest Sums(Uva 11997) 多路归并+优先队列
- UVA K Smallest Sums(多路归并,优先队列)
- UVa 11997 K Smallest Sums (优先队列 & k路归并化为两两归并)
- UVA 11997--K Smallest Sums+优先队列用于多路归并
- C# MVC 项目的创建和发布过程
- 正则表达式基本语法
- oracle 查看用户表数目,表大小,视图数目等(转自新浪博客)
- Linux 下编译安装OpenCV
- OGNL(Object-Graph Navigation Language):图形化对象导航语言
- uva 11997 K Smallest Sums 优先队列
- android 安全攻防权威指南
- Shell脚本处理“integer expression expected”
- Linux下安装Matlab2014及破解
- 算法导论—基于BFS的图算法
- PHP中的数组指针
- 想成为优秀的程序员真的很难?
- 网络爬虫 介绍
- 什么情况需要 if (log.isDebugEnabled()) {}