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("
");
44     }
45     return 0;
46 }
“这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
原文地址:https://www.cnblogs.com/Blogggggg/p/8657797.html