题目: You’re given k arrays, each array has k integers. There are kk 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
【多路归并问题】
要用优先队列logk
k个序列,k个数,两两归并
时间复杂度O(k^2*logk)
#include<iostream>
#include<cstdio>
#include<ctime>
#include<algorithm>
#include<queue>
using namespace std;
const int N=760;
int n,A[N],B[N];
inline int readin(){
int res = 0;
char ch;
while((ch = getchar())>'9'||ch <'0');
res= ch-'0';
while((ch = getchar())>='0'&&ch <='9')
res= res* 10+ch -'0';
return res;
}
struct ii{
int s,b;
ii(int s = 0,int b =0):s(s),b(b){ }
bool operator <(const ii &a)const {
if(s^a.s)return s>a.s;
}
};//a[1]+b[1]<a[1]+b[2]……,b 有序的,s=a[i]+b[j] ->s'=s-b[j]+b[j+1],只需要存储s,b
void merge(){//two merge
priority_queue<ii>q;
for(int i = 1; i<= n;i++)
q.push(ii(A[i]+B[1],1));
for(int i = 1; i<= n;i++)//push n min into C[N]
{
ii tmp=q.top();
q.pop();
A[i]=tmp.s;
int b =tmp.b;
if(b+1<=n)q.push(ii(tmp.s-B[b]+B[b+1],b+1));//贪心的思维,,取当前最小的下一个
}//最多n-1次,所以如果一直在一个序列,最多可能有一次会多余
}
int main(){
freopen("Uva.in","r",stdin);
freopen("Uva.out","w",stdout);
while((scanf("%d",&n)==1)&&n){
for(int i = 1; i<= n;i++)
A[i]=readin();
sort(A+1,A+n+1);
for(int o=2; o <= n; o++){
for(int i = 1; i<= n;i++)
B[i]=readin();
sort(B+1,B+n+1);
merge();//指针传值再到A数组
}
printf("%d",A[1]);
for(int i = 2; i<= n;i++)
printf(" %d",A[i]);
printf("\n");
}
return 0;
}