UVa 11997 K Smallest Sums (K路归并)

 K Smallest Sums

Description

You’re given k arrays, each array has k integers. There are k k 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).

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

Sample Output

9 10 12

2 2

题意:给你K个数组,每个数组有K个数,从每个数组中选一个数,一共有K^K个组合,求最小的K个数

分析:先看一个简单的版本:K=2时,这个问题就可以转化为多路归并的问题了,建一个二维数组:

1: a1+b1<=a2+b1<=a3+b1<=.......<=an+b1

2: a1+b2<=a2+b2<=a3+b2<=.......<=an+b2

............

n: a1+bn<=a2+bn<=a3+bn<=.......<=an+bn

这个我们可以用一个二元组来表示(s,k),s表示ai+bj,k=j。然后初始将(ai,b1)的所有组合放到优先队列里面,每次取出一个,将a的下标加一,再放入优先队列中,做n次即可。

对于K个,我们只需两两进行上面的操作就行了。

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1000;
struct Node
{
    int sum,k;//k代表b的下标
    bool operator<(const Node& rhs) const
    {
        return sum>rhs.sum;
    }
};
int a[MAXN][MAXN];

void Merge(int* A,int* B,int* C,int n)
{
    priority_queue<Node> q;
    for(int i=1;i<=n;i++)
    {
        Node aa;
        aa.sum=A[i]+B[1];
        aa.k=1;
        q.push(aa);
    }
    for(int i=1;i<=n;i++)
    {
        Node aa=q.top();
        q.pop();
        C[i]=aa.sum;
        int k=aa.k;
        if(k<n)
        {
            aa.sum=aa.sum-B[k]+B[k+1];
            aa.k++;
            q.push(aa);
        }
    }
}

int main()
{
    int n;
    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]+n+1);
        }
        for(int i=2;i<=n;i++)
        Merge(a[1],a[i],a[1],n);
        for(int i=1;i<=n;i++)
        {
            printf("%d",a[1][i]);
            if(i!=n) printf(" ");
            else printf("
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wangdongkai/p/5716814.html