• 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;
    }
  • 相关阅读:
    声音走样
    Terrain
    输出循环小数
    解决代码中多余的空行
    与二进制有关的几道面试题
    反转一个整数
    DirectX常见编译错误及解决办法
    STLset
    Visual Studio Autoexpand Information for DirectX 9
    素数环谈代码优化
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5716814.html
Copyright © 2020-2023  润新知