zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    变量的创建和初始化
    HDU 1114 Piggy-Bank (dp)
    HDU 1421 搬寝室 (dp)
    HDU 2059 龟兔赛跑 (dp)
    HDU 2571 命运 (dp)
    HDU 1574 RP问题 (dp)
    HDU 2577 How to Type (字符串处理)
    HDU 1422 重温世界杯 (dp)
    HDU 2191 珍惜现在,感恩生活 (dp)
    HH实习 acm算法部 1689
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5716814.html
Copyright © 2011-2022 走看看