POJ 2442.Sequence

2015-07-14

问题简述:

  输入 m 条序列,每条序列有 n 个整数。对每一个序列取一个数,可随机取出 m 个数,求这 m 个数的和,会有 m^n 种情况,输出其中和最小的 n 个数。

  原题链接:http://poj.org/problem?id=2442

解题思路:

  暴力求解会遍历 m^n 次,时间复杂度太高,不适合这个题,故采用其他方法,比如堆。

  运算过程中,我们只需要维护好大小为 n 的堆,以实现最后这个堆就是所求 n 个数。

    构造一个和序列 sum,初始化和序列 sum 为第一个序列;

    从第二个序列开始,对每一个序列计算下一个序列的第一个数与当前和序列的和,存在一个新序列 ans 中。

      用下一个序列的下一个数与当前和序列的每一个数相加,将和值与 ans 比较,若小于 ans 中的最大数,则将此和值插入 ans。

  注:以上过程每一次使用一个新序列时,都需要对其进行升序排列。

源代码:

 1 /*
 2 OJ: POJ
 3 ID: 3013216109
 4 TAST: 2442.Sequence
 5 LANG: C++
 6 NOTE: STL堆
 7 */
 8 #include <cstdio>
 9 #include <algorithm>
10 using namespace std;
11 
12 const int MAX_M=105,MAX_N=2005;
13 int a[MAX_M][MAX_N];
14 int sum[MAX_N],ans[MAX_N];
15 
16 int main()
17 {
18     int t,m,n,i,j,k;
19     scanf("%d",&t);
20     while(t--) {
21         scanf("%d %d",&m,&n);
22         for(i=0;i<m;i++)
23             for(j=0;j<n;j++)
24                 scanf("%d",&a[i][j]);
25         for(j=0;j<n;j++)
26             sum[j]=a[0][j];
27 
28         for(i=1;i<m;i++) {
29             sort(sum,sum+n);
30             sort(a[i],a[i]+n);
31             for(k=0;k<n;k++)
32                 ans[k]=sum[k]+a[i][0];
33             make_heap(ans,ans+n);
34             for(j=1;j<n;j++) {
35                 for(k=0;k<n;k++) {
36                     int x=sum[k]+a[i][j];
37                     if(x<ans[0]) {
38                         pop_heap(ans,ans+n);
39                         ans[n-1]=x;
40                         push_heap(ans,ans+n);
41                     }
42                     else break;
43                 }
44             }
45             for(j=0;j<n;j++)
46                 sum[j]=ans[j];
47         }
48         sort(sum,sum+n);
49         for(j=0;j<n-1;j++)
50             printf("%d ",sum[j]);
51         printf("%d\n",sum[n-1]);
52     }
53     return 0;
54 }

 

posted @ 2015-07-14 16:06  ACMan  阅读(362)  评论(0编辑  收藏  举报