[uva11997]k个最小和

一个k*k的矩阵,每行选取一个数相加则得到一个和,求最小的前k个和。

k<=750

 

已知前m行最小的前k个和d[1]…d[k],则前m+1行最小的前k个和都必定是d[i](i<=k)+a[m+1][x]。排序,枚举x,用优先队列处理。

学会了个小技巧:

node形式的优先队列,想直接插入元素组成node

  struct node里加一句node (int sum,int b):sum(sum),b(b) {} 实际调用:q.push(node(sum,b));  

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #include<map>
 9 #include<queue>
10 using namespace std;
11 
12 const int K=800;
13 int k,a[K][K];
14 bool cmp(int x,int y){return x<y;}
15 
16 struct node{
17     int sum,b;
18     node (int sum,int b):sum(sum),b(b) {}
19     bool operator < (const node &x) const {
20         return sum > x.sum;
21     }
22 };
23 
24 priority_queue<node> q;
25 
26 void my_merge(int *A,int *B)
27 {
28     while(!q.empty()) q.pop();
29     for(int i=1;i<=k;i++) q.push(node(A[i]+B[1],1));
30     for(int i=1;i<=k;i++)
31     {
32         node x=q.top();q.pop();
33         A[i]=x.sum;
34         if(x.b<=k-1) q.push(node(x.sum-B[x.b]+B[x.b+1],x.b+1));
35     }
36 }
37 
38 int main()
39 {
40     // freopen("a.in","r",stdin);
41     // freopen("a.out","w",stdout);
42     
43     while(scanf("%d",&k)!=EOF)
44     {
45         for(int i=1;i<=k;i++)
46             for(int j=1;j<=k;j++)
47                 scanf("%d",&a[i][j]);
48                 
49         sort(a[1]+1,a[1]+k+1,cmp);
50         for(int i=1;i<k;i++)
51         {
52             sort(a[i+1]+1,a[i+1]+k+1,cmp);
53             my_merge(a[1],a[i+1]);
54         }
55         printf("%d",a[1][1]);
56         for(int i=2;i<=k;i++) printf(" %d",a[1][i]);printf("\n");
57     }
58     
59     return 0;
60 }

 

posted @ 2018-08-11 12:24  拦路雨偏似雪花  阅读(334)  评论(0编辑  收藏  举报