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 }

 

你可能感兴趣的:(uva)