UVA11997 K Smallest Sums

Posted r-q-r-q

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA11997 K Smallest Sums相关的知识,希望对你有一定的参考价值。

题目

一句话题意 , 有 k 个长为 k 的序列 , 从其中每个序列选一个数 (k^k) 个和中输出前k小

考虑 有两个长为n的序列 , 从他们中选出(n)最小的和 , 可以用一个很妙的想法

在优先队列里 , 存((a_1 + b_1 , 1) , (a_2 + b_1 , 1) , (a_3 + b_1 , 1) dots)

第一个是 a+b , 第二项是b的下标 , 每次取出最小的 , 然后把 (x - b[id] + b[id] + 1) 放进去(b 是排好序的)

取 n 遍就行, 而有 k 个的序列的情况两两合并就可以了,正确性贪心可证 ,不写了。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 756;
int n;
int a[N] , b[N];
priority_queue< pair<int,int> , vector< pair<int,int> > , greater< pair<int,int> > > q; 
void Merge()
{
    while(q.size()) q.pop();
    for(int i = 1 ; i <= n ; ++i) q.push(make_pair(a[i] + b[1] , 1));
    int tot = 0;
    while(q.size())
    {
        int x = q.top().first , y = q.top().second; q.pop();
        a[++tot] = x; if(tot == n) break; 
        if(y < n) q.push(make_pair(x - b[y] + b[y+1] , y+1));
    }
    return ;
}

int main()
{
    while(scanf("%d" , &n) == 1)
    {
        for(int i = 1 ; i <= n ; ++i) scanf("%d",&a[i]); // 这里要先读进去一遍a , 不然直接合并就是 n 个 0 与 b 合并 
        for(int j = 2 ; j <= n ; ++j)
        {
            for(int i = 1 ; i <= n ; ++i) scanf("%d",&b[i]);
            sort(b + 1 , b + 1 + n);
            Merge();
        }
        printf("%d",a[1]);
        for(int i = 2 ; i <= n ; ++i) printf(" %d" , a[i]); puts("");
    }
    return 0;
}

以上是关于UVA11997 K Smallest Sums的主要内容,如果未能解决你的问题,请参考以下文章

UVA 11997 K Smallest Sums 优先队列 多路合并

优先队列UVa11997K Smallest Sums

UVA11997 K Smallest Sums

UVA 11997 K Smallest Sums 优先队列+归并 STL

UVa 11997 K Smallest Sums 优先队列&&打有序表&&归并

UVA.11997- K Smallest Sums, OJ4TH.368 - Magry's Sum I