UVa 11997 K Smallest Sums - 优先队列


  题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和。

  考虑将前i个数组合并,保留前k个和。然后考虑将第(i + 1)个数组和它合并,保留前k个和。

  如果暴力的话就进行就暴力枚举每一对,然后进行求和,然后再选出前k个,然而这样会TLE。

  可以考虑将另外一个数组进行排序。然后可以看做是k个已经排好序的数组进行归并

{A[1] + B[1], A[1] + B[2], ...}
{A[2] + B[1], A[2] + B[2], ...}
{A[3] + B[1], A[3] + B[2], ...}
.
.
.
{A[k] + B[1], A[k] + B[2], ...}

  对于每个数组,只有前一个值被取了,后一个值才有可能被取。

  所以用一个优先队列进行维护,先将所有数组的第一个元素放进去,然后每次取出一个元素,再将它的后一个放入队列。

  每次合并时间复杂度O(klogk),所以总时间复杂度为O(k2logk)

Code

 1 /**
 2  * UVa
 3  * Problem#11997
 4  * Accepted
 5  * Time: 190ms
 6  */
 7 #include <bits/stdc++.h>
 8 using namespace std;
 9 typedef bool boolean;
10 
11 int k;
12 int A[751], B[751], C[751];
13 int *X, *Y;
14 
15 typedef class Item {
16     public:
17         int x, b;
18         
19         Item(int x = 0, int b = 0):x(x), b(b) {        }
20         
21         boolean operator < (Item xb) const {
22             return X[x] + B[b] > X[xb.x] + B[xb.b];
23         }
24         
25         int getVal() {
26             return X[x] + B[b];
27         }
28 }Item;
29 
30 inline void merge() {
31     priority_queue<Item> que;
32     for(int i = 0; i < k; i++)
33         que.push(Item(i, 0));
34     
35     for(int i = 0; i < k; i++) {
36         Item e = que.top();
37         que.pop();
38         Y[i] = e.getVal();
39         que.push(Item(e.x, e.b + 1));
40     }
41     while(!que.empty())    que.pop();
42     swap(X, Y);
43 }
44 
45 inline boolean init() {
46     if(scanf("%d", &k) == EOF)    return false;
47     X = A, Y = C;
48     for(int i = 0; i < k; i++)
49         scanf("%d", X + i);
50     sort(A, A + k);
51     for(int i = 1; i < k; i++) {
52         for(int j = 0; j < k; j++)
53             scanf("%d", B + j);
54         sort(B, B + k);
55         merge();
56     }
57     return true;
58 }
59 
60 inline void solve() {
61     for(int i = 0; i < k - 1; i++)
62         printf("%d ", X[i]);
63     printf("%d\n", X[k - 1]);
64 }
65 
66 int main() {
67     while(init()) {
68         solve();
69     }
70     return 0;
71 }
posted @ 2017-11-07 07:49  阿波罗2003  阅读(389)  评论(0编辑  收藏  举报