uva 11997 K Smallest Sums
首先对每行进行排序,并对与前两行有$A = a_1 \leq a_2 \leq \cdots \leq a_k$和$B = b_1 \leq b_2 \leq \cdots \leq b_k$。首先把所有的$b_i , i\in [1,k]$与$a_1$进行求和,并加入优先队列中。其中最小的必然是$a_1+b_1$,在优先队列队首。然后只需在优先队列中压入$a_1+b_2$,没有压入$a_2+b_1$原因是该和已经在队列中存在了,没有压入$a_2+b_2$的原因是$a_2+b_2 \leq a_1 + b_2$因此无需压入。
从而循环往复,对所有的k行都进行上面的操作。即可取出最小的k个和。
代码如下:
1 #include <iostream> 2 #include <queue> 3 #include <string> 4 #include <cstdio> 5 #include <algorithm> 6 using namespace std; 7 int arr[800][800]; 8 int k; 9 class node 10 { 11 public: 12 int num, sum; 13 node(int n, int s) 14 { 15 num = n; 16 sum = s; 17 } 18 bool operator < (const node & n)const 19 { 20 return sum > n.sum; 21 } 22 23 }; 24 void merge(int *a, int *b, int *res, int k) 25 { 26 priority_queue<node> q; 27 28 node tmp(0,0); 29 for( int i = 0 ; i < k ; i++ ) 30 { 31 tmp.sum = a[i] + b[0]; 32 tmp.num = 0; 33 q.push(tmp); 34 } 35 for( int i = 0 ; i < k ; i++ ) 36 { 37 tmp = q.top(); 38 res[i] = q.top().sum; 39 q.pop(); 40 if(tmp.num + 1 < k) 41 { 42 tmp.sum = tmp.sum - b[tmp.num] + b[tmp.num+1]; 43 tmp.num++; 44 q.push(tmp); 45 } 46 } 47 } 48 int main(int argc, char *argv[]) 49 { 50 while( scanf("%d", &k ) != EOF) 51 { 52 for( int i = 0 ; i < k ; i++ ) 53 { 54 for( int j = 0 ; j < k ; j++ ) 55 { 56 scanf("%d", &arr[i][j]); 57 } 58 sort(arr[i], arr[i]+k); 59 } 60 for(int i = 1 ; i < k ; i++ ) 61 merge(arr[0], arr[i], arr[0], k); 62 for(int i = 0 ; i < k ; i++ ) 63 printf("%d%s",arr[0][i],i != k-1?" ":"\n"); 64 } 65 }