UVA 11997 K Smallest Sums

   

  先看简化版:给出2个长度为n的有序表A和B,分别在A和B中任取一个数相加,可以得到n^2个和,求这些和中最小的n个和。
  解决了简化版,那么一样的一组一组合并就好了。
    转化为多路归并问题。
    我们先把这n^2个数组织成如下n个有序列。
    列1:A1+B1<=A1+B2<=A1+B3...列2:A2+B1<=A2+B2<=A2+B3...
    列n:An+B1<=An+B2<=An+B3...
    用一个struct(s,b)表示一个元素
    其中s=Aa+Bb,这样我们要得到(s,b)的下一个(s',b+1), 只要使s'=s-Bb+B(b+1)即可。
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <map>
 4 #include <vector>
 5 #include <functional>
 6 #include <string>
 7 #include <cstring>
 8 #include <queue>
 9 #include <set>
10 #include <cmath>
11 #include <cstdio>
12 
13 
14 using namespace std;
15 #define IOS ios_base::sync_with_stdio(false)
16 typedef long long LL;
17 const int INF = 0x3f3f3f3f;
18 const double PI=4.0*atan(1.0);
19 
20 const int maxn=800;
21 typedef struct Item{
22     int s,b;
23     Item(int s,int b):s(s),b(b){}
24     bool operator<(const Item &a) const{
25         return s>a.s;
26     }
27 }I;
28 int k,a[maxn],b[maxn];
29 void merge(int *a,int *b,int *c)
30 {
31     sort(a,a+k);
32     sort(b,b+k);
33     priority_queue<I> que;
34     for(int i=0;i<k;i++)
35         que.push(I(a[i]+b[0],0));
36     for(int i=0;i<k;i++){
37         I it=que.top(); que.pop();
38         c[i]=it.s;
39         if(it.b<k-1) que.push(I(it.s-b[it.b]+b[it.b+1],it.b+1));
40     }
41 }
42 int main()
43 {
44     while(scanf("%d",&k)!=EOF){
45         for(int i=0;i<k;i++) scanf("%d",&a[i]);
46         for(int i=0;i<k-1;i++){
47             for(int j=0;j<k;j++) scanf("%d",&b[j]);
48             merge(a,b,a);
49         }
50         for(int i=0;i<k-1;i++) printf("%d ",a[i]);
51         printf("%d
",a[k-1]);
52     }
53 }
原文地址:https://www.cnblogs.com/cumulonimbus/p/5863678.html