题目大致的意思是有K个长度为K的数组,在每个数组中取一个元素求和,要求出所有和中前K小的。
解决的思路是:
首先我们可以想到两个有序数组进行求和时,可以看做有K个表:
1. A[0] + B[0] <= A[0] + B[1]...... <= A[0] + B[K-1].
2. A[1] + B[0] <= A[1] + B[1]...... <= A[1] + B[K-1].
... ... ...
我们可以用一个优先队列来维护,一开始先取每个表头的元素入队,然后每次取最小的出队,将该表的下一个元素入队,另外还需要注意的是,优先队列的话,我们只需要保存和s,以及该位置下B的下标t即可,因为下一个和的值即为s - B[t] + B[t+1].
两个表的按照以上思路完成即可,对于此题的多个表,进行两两合并就好了......
#include "stdio.h"
#include "string.h"
#include "math.h"
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXM 1
#define MAXN 1
#define max(a,b) a > b ? a : b
#define min(a,b) a < b ? a : b
#define Mem(a,b) memset(a,b,sizeof(a))
int Mod = 1000000007;
double pi = acos(-1.0);
double eps = 1e-6;
typedef struct{
int f,t,w,next;
}Edge;
Edge edge[MAXM];
int head[MAXN];
int kNum;
typedef long long LL;
void addEdge(int f, int t, int w)
{
edge[kNum].f = f;
edge[kNum].t = t;
edge[kNum].w = w;
edge[kNum].next = head[f];
head[f] = kNum ++;
}
int num[755][755];
//定义优先队列
struct Node{
int t, v;
Node(int t, int v): t(t), v(v){}
bool operator < (const Node a) const{ //要是const
return v > a.v;
}
};
int n;
int C[755];
priority_queue<Node> q;
void Merge(int *A, int *B, int n){
for(int i = 0; i < n; i ++){
q.push(Node(0, A[i] + B[0]));
}
for(int i = 0; i < n; i ++){
C[i] = q.top().v;
int t = q.top().t;
q.pop();
q.push( Node(t+1, C[i]- B[t] + B[t+1]) );
}
while(!q.empty()) q.pop();
for(int i = 0; i < n; i ++){
A[i] = C[i];
}
}
void solve(){
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
cin>>num[i][j];
}
sort(num[i], num[i] + n);
}
for(int i = 1; i < n; i ++){
Merge(num[0], num[i], n);
}
for(int i = 0; i < n; i ++){
if(i == 0){
printf("%d", num[0][i]);
}
else{
printf(" %d", num[0][i]);
}
}
printf("\n");
}
int main()
{
// freopen("d:\\test.txt", "r", stdin);
while(cin>>n){
solve();
}
return 0;
}