题解——UVA11997 K Smallest Sums

题面

  背景

  输入

  

  输出

    

翻译(渣自翻)

  给定K个包含K个数字的表,要求将其能产生的\( k^{k} \)个值中最小的K个输出出来

题解

k路归并问题的经典问题

可以转化为二路归并问题求解

考虑A[],B[]两个有序数组

使用堆,记录一些二元组\( (x,y) \),x表示值,y表示对应的b的下标,因为我们是把b合并到a上,所以我们能够根据记录的下标推出后面的值

然后两两合并

所以就很简单

放代码

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
struct asshole{
    int w,t;
    bool operator < (const asshole b) const{
        return w>b.w;
    }
};
priority_queue<asshole> q;
int kz[10000],kk[10000];
int n;
void merge(int *a,int *b,int *c){
    while(!q.empty())
        q.pop();
    for(int i=1;i<=n;i++)
        q.push((asshole){a[i]+b[1],1});
    for(int i=1;i<=n;i++){
        asshole in = q.top();
        q.pop();
        a[i]=in.w;
        int pos=in.t;
        if(pos+1<=n)
            q.push((asshole){in.w-b[pos]+b[pos+1],pos+1});
    }
}
int main(){
    while(scanf("%d",&n)==1){
        for(int i=1;i<=n;i++)
            scanf("%d",&kz[i]);
        sort(kz+1,kz+n+1);
        for(int j=1;j<=n-1;j++){
        for(int i=1;i<=n;i++)
            scanf("%d",&kk[i]);
        sort(kk+1,kk+n+1);
        merge(kz,kk,kz);
        }
        for(int i=1;i<=n-1;i++)
            printf("%d ",kz[i]);
        printf("%d",kz[n]);
        printf("\n");
    }
}

 

posted @ 2018-08-15 21:27  dreagonm  阅读(130)  评论(0编辑  收藏  举报