1. 程式人生 > >題解——UVA11997 K Smallest Sums

題解——UVA11997 K Smallest Sums

clas 題解 smallest [] 下標 src spa con png

題面

  背景

技術分享圖片

  輸入

  技術分享圖片

  輸出

    技術分享圖片

翻譯(渣自翻)

  給定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"); } }

題解——UVA11997 K Smallest Sums