uva 11997 K Smallest Sums 优先队列
2015-09-15 16:44
399 查看
题目:https://uva.onlinejudge.org/external/119/11997.pdf
对于两组数a
,b
,每组长度为n,现在要得到a[i]+b[j] (1<=i,j<=n)的和 中前n小的值。
先对b
排序
方法是利用b[1] + x<b[2]+x<...<b
+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a
+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
,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
+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)
对于两组数a
,b
,每组长度为n,现在要得到a[i]+b[j] (1<=i,j<=n)的和 中前n小的值。
先对b
排序
方法是利用b[1] + x<b[2]+x<...<b
+x;
构造一个优先队列(小的优先)
先放入n个值 (a[1]+b[1]、a[2]+b[1]、a[3]+b[1]、......、a
+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
,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
+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 yskysker123 int 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] ); } 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 second using 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);
相关文章推荐
- This page can't be displayed. Contact support for additional information. The incident ID is: xxxxxx
- dp、px 等单位转换
- 在Linux上rpm安装运行Redis 3.0.4
- C# window Service实现调用有UI的应用程序(关于win xp以后的window系统)
- 关于haproxy负载均衡的算法整理
- cocos2d-js 的project.json
- android 自定义dialog 带动画的
- Java、OC点语法的区别
- C#格式化数值结果表
- Win 7文件名或扩展名太长无法删除
- codeforces 340D D. Bubble Sort Graph(dp+线段树)
- Codeforces Round #277.5 (Div. 2)A——SwapSort
- Qt 学习之路 2(79):QML 组件
- nginx不支持.htaccess解决办法
- SQLite事务管理
- 一步一步配置NLB(续)之深入测试
- 一步一步配置NLB
- JSTL标签库 fmt标签
- NHibernate从入门到精通系列(7)——多对一关联映射
- poj2479动态规划+两个子串最大和,一个从左往右扫描,一个从右往左扫描时在分割点变化时,找出最大的分割点是的值ans