POJ2442 Sequence

题目链接:https://vjudge.net/problem/POJ-2442

题目大意:

  有 \(m\) 个序列,每个序列 \(n\) 个数。在每个序列中选一个数,会选出 \(m\) 个数,对应一个和。那么对于所有的数,总共有 \(m^n\) 种选法,要求从小到大输出其中和最小的 \(n\) 种选法对应的和。

知识点:  优先队列

解题思路:

  对于 \(2\) 个序列,我们可以先把这两个序列从小到大排序,然后用第一个序列的第一项分别去加第二个序列的各项,得到 \(n\) 个和,放到一个优先队列(大顶堆)中;接下来用第一序列的第二项分别去加第二序列的各项,如果和小于优先队列的首项,那么首项出队,新的和入队,否则结束对第一序列第二项的操作,转而操作第一序列第三项;如此进行直到操作完第一序列的所有项,得到了第一第二序列各项相加的前 \(n\) 小的和。

  那么对于 \(3\) 个序列的问题,我们可以先用上述方法合并前两个序列,得到一个 \(n\) 项的序列,再和第三序列合并出答案。至于大于 \(3\) 个序列的问题要怎么做,相信读者自己心里已经有答案了吧。

AC代码:

 1 #include <iostream>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 int m,n;
 9 int inp[105][2005];
10 priority_queue<int> q;
11 int main(){
12     int T;
13     scanf("%d",&T);
14     while(T--){
15         scanf("%d%d",&m,&n);
16         for(int i=1;i<=m;i++){
17             for(int j=1;j<=n;j++)
18                 scanf("%d",&inp[i][j]);
19             sort(inp[i]+1,inp[i]+1+n);
20         }
21         for(int i=1;i<m;i++){
22             for(int j=1;j<=n;j++)   q.push(inp[i][1]+inp[i+1][j]);
23             for(int j=2;j<=n;j++){
24                 for(int k=1;k<=n;k++){
25                     if(inp[i][j]+inp[i+1][k]>=q.top())   break;
26                     else{
27                         q.pop();
28                         q.push(inp[i][j]+inp[i+1][k]);
29                     }
30                 }
31             }
32             int ind=n;
33             while(!q.empty()){
34                 inp[i+1][ind]=q.top();
35                 q.pop();
36                 ind--;
37             }
38         }
39         for(int i=1;i<=n;i++){
40             if(i!=1)    printf(" ");
41             printf("%d",inp[m][i]);
42         }
43         printf("\n");
44     }
45     return 0;
46 }

 

posted @ 2018-03-27 15:38  Blogggggg  阅读(198)  评论(0编辑  收藏  举报