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。

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

源代码:

/*
OJ: POJ
ID: 3013216109
TAST: 2442.Sequence
LANG: C++
NOTE: STL堆
*/
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAX_M=105,MAX_N=2005;
int a[MAX_M][MAX_N];
int sum[MAX_N],ans[MAX_N];

int main()
{
    int t,m,n,i,j,k;
    scanf("%d",&t);
    while(t--) {
        scanf("%d %d",&m,&n);
        for(i=0;i<m;i++)
            for(j=0;j<n;j++)
                scanf("%d",&a[i][j]);
        for(j=0;j<n;j++)
            sum[j]=a[0][j];

        for(i=1;i<m;i++) {
            sort(sum,sum+n);
            sort(a[i],a[i]+n);
            for(k=0;k<n;k++)
                ans[k]=sum[k]+a[i][0];
            make_heap(ans,ans+n);
            for(j=1;j<n;j++) {
                for(k=0;k<n;k++) {
                    int x=sum[k]+a[i][j];
                    if(x<ans[0]) {
                        pop_heap(ans,ans+n);
                        ans[n-1]=x;
                        push_heap(ans,ans+n);
                    }
                    else break;
                }
            }
            for(j=0;j<n;j++)
                sum[j]=ans[j];
        }
        sort(sum,sum+n);
        for(j=0;j<n-1;j++)
            printf("%d ",sum[j]);
        printf("%d\n",sum[n-1]);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章