题解——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"); } }