首页 > 代码库 > 多路归并优先队列——UVA 11997
多路归并优先队列——UVA 11997
K Smallest Sums
You‘re given k arrays, each array has k integers. There are kk ways to pick exactly one element in each array and calculate the sum of the integers. Your task is to find the k smallest sums among them.
Input
There will be several test cases. The first line of each case contains an integer k (2<=k<=750). Each of the following k lines contains k positive integers in each array. Each of these integers does not exceed 1,000,000. The input is terminated by end-of-file (EOF). The size of input file does not exceed 5MB.
Output
For each test case, print the k smallest sums, in ascending order.
Sample Input
3 1 8 5 9 2 5 10 7 6 2 1 1 1 2
Output for the Sample Input
9 10 12 2 2
题意:有K个整数数组,包含K个元素。在每个数组中取一个元素加起来,可以得到k^k个和。求这些和中最小的K个值
分析:这题有简化版本的,即2个整数数组A,B,包含K个元素,在每个数组中取一个元素加起来,可以得到k^2个和,求这些和中最小的K个值。
我们需要把这k^2个和组织成如下k个有序表.
表1:A1+B1<=A1+B2<=......<=A1+Bk
表2: A2+B1<=A2+B2<=......<=A2+Bk
表k:Ak+B1<=AK+B2<=......<=Ak+Bk
我们可以用二元组(s,b)来表示一个元素即s=Aa+Bb;为什么不保存A的下标a呢?因为我们用不到a的值。如果我们需要元素(s,b)在表a的下一个元素(s‘,b+1).只需要计算s‘=s+B[b+1]-B[b];
这样我们先将K个表的第一个元素压入优先队列,这样队列中就用k个元素了。然后从队列中出一个值,就压入这个值所在表的下一个元素,直到k个值都出了优先队列。这样就得到k个最小值了
别人的讲解,非常详细!
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<stack> #include<vector> #include<algorithm> #include<cstring> #include<string> #include<iostream> #define ms(x,y) memset(x,y,sizeof(x)) const int MAXN=750+10; const int INF=1<<30; using namespace std; int a[MAXN]; int b[MAXN]; struct Pair { int val, dex; Pair(){} Pair(int v, int d):val(v),dex(d){} friend bool operator < (Pair const p1, Pair const p2) { return p1.val > p2.val; } }; int main() { //freopen("in.txt","r",stdin); int n; while(~scanf("%d", &n)) { for(int i=0; i<n; i++) scanf("%d", a+i); sort(a, a+n); for(int i=1; i<n; i++){ for(int j=0; j<n; j++) scanf("%d", b+j); sort(b, b+n); int cnt = 0; priority_queue<Pair>pq; for(int v=0; v<n; v++) pq.push(Pair(a[v] + b[0], 0)); Pair p; while(!pq.empty()) { p = pq.top(); a[cnt++] = p.val; if(cnt == n) break; pq.pop(); p.dex++; pq.push(Pair(p.val - b[p.dex-1] + b[p.dex], p.dex)); } } printf("%d", a[0]); for(int i=1; i<n; i++) printf(" %d", a[i]); printf("\n"); } return 0; }
多路归并优先队列——UVA 11997