【暑假】[实用数据结构]UVa11997 K Smallest Sums

UVa11997 K Smallest Sums

 题目:

                                                        K Smallest Sums

 

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). The size of input file does not exceed 5MB.

 

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

 

Output for the Sample Input

 

9 10 12
2 2

------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

思路:

 先思考2个有序表(sort后)AB合成的情况。组织如下

【 表】1: A1+B1 <=  A1+B2 <=  A1+B3 <=......

 【表】2:A2+B1 <=  A2+B2 <=  A2+B3 <=......

 ......

 【表】n:An+B1 <=  An+B2 <=  An+B3 <=......

转化为多路归并问题且有总数限制为k,因此将n个【表】合并为一个有序【表】C且表中数据数目为k。优先队列处理:初始化优先队列为n个表的第一元素,每次在队列中取出最小元素加入C并将该最小元素在【表】中的后一个元素入队。共取k个元素。

对于k个有序表的情况:两两合并。

 

于是有代码如下:

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 #define FOR(a,b,c) for(int a=(b);a<(c);a++)
 5 using namespace std;
 6 
 7 const int maxn = 800 + 10;
 8 
 9 struct Node{
10     int s,b;
11     bool operator <(const Node& rhs) const{ //相反定义 < 
12       return s>rhs.s; 
13     }
14 };
15 
16 
17 void merge(int* A,int* B,int*C,int n){ //合并AB数组取其前n小的和放入C 
18 priority_queue<Node> Q;
19   FOR(i,0,n) Q.push(Node{A[i]+B[0],0});
20   FOR(i,0,n){
21       Node u=Q.top();Q.pop();
22       C[i]=u.s;
23       int b=u.b;
24       if(b+1 < n) Q.push(Node{u.s-B[b]+B[b+1],b+1}); //加入A[a][b+1] 
25   }    
26 }
27 
28 int main(){
29 int n;
30 int A[maxn],B[maxn];
31 
32   while(scanf("%d",&n)==1){
33       FOR(j,0,n) scanf("%d",&A[j]); sort(A,A+n);
34       FOR(i,1,n){
35            FOR(j,0,n) scanf("%d",&B[j]);
36            sort(B,B+n);
37          merge(A,B,A,n);
38     }
39     printf("%d",A[0]); 
40     FOR(i,1,n)
41       printf(" %d",A[i]);
42     printf("\n");
43  }
44  return 0;
45 }

 

你可能感兴趣的:(【暑假】[实用数据结构]UVa11997 K Smallest Sums)