UVA 11997 STL 优先队列

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3148

题意:给K个数组,每个数组含有K个整数,从每个数组中各选一个数加起来,得到一个sum,这样的选法一共有K^k种,现在求这样的和中最小的K个sum.

解法:先考虑两个数组的情形

假设A1<=A2<=`````<=AK

B1<=B2<=`````<=Bk

则有

A1+B1<=A1+B2<=`````<=A1+Bk.

A2+B1<=A2+B2<=`````<=A2+Bk.

```````

Ak+B1<=Ak+B2<=`````<=Ak+Bk.

首先把第一列的数<s[i] = A[i] + B[1]     ,      1>,第一个数为和,第二个数为B的序号,放入优先队列,然后从优先队列中弹出最小的,这个最小值一定是所有和中最小的,同时压入A[a] + B[b+1],A[a]+B[b+1] = s-B[b]+B[b+1]....这样循环n次即可。得到了n个最小和。因为这里有k个数组,两两合并即可。

以上摘自刘汝佳的大白书190页。(是看了他的书写的,如果有错了不是他写错了,必然是我写错了)

贴代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 using namespace std;
 5 #define N 755
 6 int k[N][N],n;
 7 struct Item
 8 {
 9     int s,b;//s = A[a] + B[b]
10     Item(int s,int b):s(s),b(b) {}
11     bool operator<(const Item & other)const
12     {
13         return s > other.s;
14     }
15 };
16 void output(int a[])
17 {
18     printf("array :
");
19     for(int i=0; i<n; ++i)
20         printf("%d ",a[i]);
21     puts("");
22 }
23 void combine(int A[],int B[])
24 {
25     priority_queue<Item> q;
26     for(int i =0; i<n; ++i)
27         q.push(Item(A[i]+B[0] , 0));
28     for(int i=0; i<n; ++i)
29     {
30         Item item = q.top();
31         q.pop();
32         A[i] = item.s;
33         int b = item.b;
34         if(b+1 < n ) q.push(Item(item.s - B[b] + B[b+1] , b+1));
35     }
36 }
37 int main()
38 {
39 //    freopen("in.txt","r",stdin);
40     while(~scanf("%d",&n))
41     {
42         for(int i=0; i<n; ++i)
43         {
44             for(int j=0; j<n; ++j)
45                 scanf("%d",&k[i][j]);
46             sort(k[i],k[i]+n);
47         }
48         for(int i=1; i<n; ++i)
49             combine(k[0],k[i]);
50         printf("%d",k[0][0]);
51         for(int i=1; i < n; ++i)
52             printf(" %d",k[0][i]);
53         puts("");
54     }
55     return 0;
56 }
View Code
原文地址:https://www.cnblogs.com/allh123/p/3287425.html