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]);
    }
}


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