题目链接:
题目描述:
有一个n*n的矩阵,在每一行取出一个数,可以得到n个数的和,问前n小的和分别是多少?
解题思路:
对于两个数组a[n],b[n],我们可以用二路归并维护一个升序序列a[i]+b[j](1<=i<=n,1<=j<=n),先把a[i]+b[1](1<=i<=n)加进优先队列,每次取出队首元素,记录下来,然后再改变为a[i]+b[j+1]再加进队列.
依次进行n-1二路合并即可。
优美的代码将要闪亮登场!!!!!
1 #include <queue> 2 #include <cstdio> 3 #include <string> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 const int maxn = 500; 8 struct node 9 { 10 int sum, num; 11 node (int a, int b):sum(a),num(b){} 12 bool operator < (const node &a) const { 13 return sum > a.sum; 14 } 15 }; 16 int maps[maxn][maxn], ans[maxn], arr[maxn]; 17 int n; 18 void Merge (int cnt) 19 { 20 priority_queue <node> Q; 21 for (int i=0; i<n; i++) 22 Q.push (node(ans[i]+maps[cnt][0], 0)); 23 for (int i=0; i<n; i++) 24 { 25 node p = Q.top (); 26 Q.pop(); 27 arr[i] = p.sum; 28 if (p.num != n) 29 { 30 p.sum += maps[cnt][p.num+1] - maps[cnt][p.num]; 31 p.num ++; 32 Q.push (p); 33 } 34 } 35 for (int i=0; i<n; i++) 36 ans[i] = arr[i]; 37 } 38 int main () 39 { 40 while (scanf ("%d", &n) != EOF) 41 { 42 for (int i=0; i<n; i++) 43 { 44 for (int j=0; j<n; j++) 45 scanf ("%d", &maps[i][j]); 46 sort (maps[i], maps[i]+n); 47 } 48 for (int i=0; i<n; i++) 49 ans[i] = maps[0][i]; 50 for (int i=1; i<n; i++) 51 Merge (i); 52 for (int i=0; i<n; i++) 53 printf ("%d%c", ans[i], i==n-1?' ':' '); 54 } 55 return 0; 56 }