USACO 3.4.4 Raucous Rockers 破鑼搖滾樂隊

一道動態規劃題,但觀察數據規模,窮舉就行了。 窮舉每首歌是否選取所有的組合可能(2^20種),算出每種情況所有光盤上一共能存的歌曲數目,保留最大值即可。

對於窮舉每首歌是否選取所有的組合可能,我採用了位運算的高效方法

limit=(1 << N)-1;
for (i=0;i<=limit;i++)

然後i對應的每種狀況計算能裝進光盤中的最大的歌曲數目即可。

USER: CmYkRgB CmYkRgB [cmykrgb1] TASK: rockers LANG: C++

Compiling... Compile: OK

Executing... Test 1: TEST OK [0.000 secs, 2844 KB] Test 2: TEST OK [0.000 secs, 2840 KB] Test 3: TEST OK [0.011 secs, 2840 KB] Test 4: TEST OK [0.000 secs, 2844 KB] Test 5: TEST OK [0.011 secs, 2844 KB] Test 6: TEST OK [0.011 secs, 2840 KB] Test 7: TEST OK [0.410 secs, 2840 KB] Test 8: TEST OK [0.454 secs, 2840 KB] Test 9: TEST OK [0.097 secs, 2844 KB] Test 10: TEST OK [0.000 secs, 2840 KB] Test 11: TEST OK [0.421 secs, 2844 KB] Test 12: TEST OK [0.454 secs, 2840 KB]

All tests OK.

/*
ID: cmykrgb1
PROG: rockers
LANG: C++
*/
#include <iostream>
#include <fstream>
#define MAX 21
using namespace std;
ifstream fi("rockers.in");
ofstream fo("rockers.out");
long N,T,M,maxr=0;
long len[MAX];

void init()
{
    long i;
    fi >> N >> T >> M;
    for (i=1;i<=N;i++)
        fi >> len[i];
}

void comser()
{
    unsigned long limit,i;
    long j,k,rec,st;
    bool A;
    long use[MAX];
    limit=(1 << N)-1;
    for (i=0;i<=limit;i++)
    {
        memset(use,0,sizeof(use));
        rec=0;st=1;
        for (j=1;j<=N;j++)
        {
            A=(i & (1 << (j-1))) >> (j-1);
            if (A) for (k=st;k<=M;k++)
                    if (use[k]+len[j]<=T)
                    {
                        use[k]+=len[j];
                        rec++;
                        st=k;
                        break;
                    }
        }
        if (rec>maxr) maxr=rec;
    }
}

void print()
{
    fo << maxr << endl;
    fi.close();
    fo.close();
}

int main()
{
    init();
    comser();
    print();
    return 0;
}

相關日誌