USACO 4.3.4 Letter Game 字母遊戲 lgame

這個題要仔細讀,理解題意。起初我理解得不對,以爲是輸出的每個結果都必須是輸入的一個排列,不能多也不能少。這種理解不正確。汗,我一直以爲樣例居然是錯的,其實使用的字典不一樣。

這道題正確的理解應該是,在結果的單詞或詞組構所成的字母中,每個字母出現的頻數不大於輸入的字符串中每個字母的頻數。也就是例如輸入是 aaa,字典中有單詞 a,aa,aaa,aaaa,其中a,aa,aaa都是符合條件的解,但只有aaa纔是要輸出的最優解。

理解題意以後編程不難,直接枚舉每種可行解,單詞可以在O(n)內解決,詞組要O(N^2)。但是對於40000個單詞但是太多了。可以發現,大多數單詞都是用不到的,而所以我們可以在讀入字典的時候直接去除非可行解的單詞,即該單詞有輸入字串中未出現的字母,或者在該單詞中的字母中,有頻數大於輸入字串所含該字母頻數的(例:輸入字串爲aabb,該單詞爲aaa,其中a的頻數大於輸入字串,必定無法有輸入字串構成)。

這樣優化可以去掉絕大部分的冗餘,使得程序能夠在很快的時間內算出結果。

所後別忘了對結果排序,可以把單詞當作一個第二個單詞爲空串的詞組,按字典順序排序即可。

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

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3476 KB]
   Test 2: TEST OK [0.000 secs, 3476 KB]
   Test 3: TEST OK [0.000 secs, 3476 KB]
   Test 4: TEST OK [0.011 secs, 3472 KB]
   Test 5: TEST OK [0.011 secs, 3476 KB]
   Test 6: TEST OK [0.000 secs, 3476 KB]
   Test 7: TEST OK [0.011 secs, 3472 KB]
   Test 8: TEST OK [0.011 secs, 3476 KB]
   Test 9: TEST OK [0.011 secs, 3476 KB]
   Test 10: TEST OK [0.011 secs, 3472 KB]
   Test 11: TEST OK [0.011 secs, 3472 KB]
   Test 12: TEST OK [0.011 secs, 3472 KB]

All tests OK.

Your program ('lgame') produced all correct answers!  This is your
submission #2 for this problem.  Congratulations!
/*
ID: cmykrgb1
PROG: lgame
LANG: C++
*/
#include <iostream>
#include <fstream>
using namespace std;
ifstream fi("lgame.in");
ifstream fd("lgame.dict");
ofstream fo("lgame.out");

typedef struct
{
    char c[7];
    int len;
    int score;
}str;

typedef struct
{
    char c1[7],c2[7];
    int len1,len2;
}Tans;

int uw['z'+1],used['z'+1];
int v['z'+1];
str S[40001];
Tans ans[50];
int N=1,L,acnt;
int Ms=0;

void init()
{
    int i;
    char c;
    bool k;
    while (!fi.eof())
    {
        c=fi.get();
        uw[c]++;
    }
    while (c!='.')
    {
        memset(used,0,sizeof(used));
        L++;
        c=fd.get();
        if (c=='.')
            break;
        k=true;
        while (c==10 || c==13)    c=fd.get();
        S[N].len=0;
        while (c!=10 && c!=13)
        {
            S[N].c[ S[N].len++ ]=c;
            used[c]++;
            if (!uw[c])
                k=false;
            c=fd.get();
        }
        S[N].c[ S[N].len ]=0;
        for (i='a';i<='z';i++)
            if (used[i]>uw[i])
            {
                k=false;
                break;
            }
        if (k)
            N++;
    }
    N--;
    v['q']=v['j']=v['z']=v['x']=7;
    v['w']=v['f']=v['k']=v['v']=6;
    v['y']=v['p']=v['g']=v['h']=v['b']=v['m']=5;
    v['u']=v['d']=v['c']=4;
    v['o']=v['l']=3;
    v['r']=v['t']=v['a']=v['n']=2;
    v['e']=v['i']=v['s']=1;
}

void findans()
{
    int i,k,p;
    for (i=1;i<=N;i++)
    {
        for (k=0;k<=S[i].len-1;k++)
            S[i].score+=v[ S[i].c[k] ];

        if (S[i].score>Ms)
        {
            Ms=S[i].score;
            acnt=1;
            for (p=0;p<=S[i].len-1;p++)
                ans[acnt].c1[p]=S[i].c[p];
            ans[acnt].len1=S[i].len;
            ans[acnt].c1[ ans[acnt].len1 ]=0;
        }
        else if (S[i].score==Ms)
        {
            acnt++;
            for (p=0;p<=S[i].len-1;p++)
                ans[acnt].c1[p]=S[i].c[p];
            ans[acnt].len1=S[i].len;
            ans[acnt].c1[ ans[acnt].len1 ]=0;
        }
    }
}

void findpair()
{
    memset(used,0,sizeof(used));
    int i,j,p;
    bool K;
    int T;
    for (i=1;i<=N-1;i++)
    {
        for (j=i+1;j<=N;j++)
        {
            T=S[i].score+S[j].score;
            for (p=0;p<=S[i].len-1;p++)
                used[S[i].c[p]]++;
            for (p=0;p<=S[j].len-1;p++)
                used[S[j].c[p]]++;
            K=true;
            for (p='a';p<='z';p++)
                if (used[p]>uw[p])
                {
                    K=false;
                    break;
                }
            memset(used,0,sizeof(used));
            if (!K) continue;
            if (T>Ms)
            {
                Ms=T;
                acnt=1;
                for (p=0;p<=S[i].len-1;p++)
                    ans[acnt].c1[p]=S[i].c[p];
                ans[acnt].len1=S[i].len;
                ans[acnt].c1[ ans[acnt].len1 ]=0;
                for (p=0;p<=S[j].len-1;p++)
                    ans[acnt].c2[p]=S[j].c[p];
                ans[acnt].len2=S[j].len;
                ans[acnt].c2[ ans[acnt].len2 ]=0;
            }
            else if (T==Ms)
            {
                acnt++;
                for (p=0;p<=S[i].len-1;p++)
                    ans[acnt].c1[p]=S[i].c[p];
                ans[acnt].len1=S[i].len;
                ans[acnt].c1[ ans[acnt].len1 ]=0;
                for (p=0;p<=S[j].len-1;p++)
                    ans[acnt].c2[p]=S[j].c[p];
                ans[acnt].len2=S[j].len;
                ans[acnt].c2[ ans[acnt].len2 ]=0;
            }
        }
    }
}


void print()
{
    fo << Ms << endl;
    int i,j;
    for (i=1;i<=acnt;i++)
    {
        for (j=0;j<=ans[i].len1-1;j++)
            fo << ans[i].c1[j];
        if (ans[i].len2)
        {
            fo << ' ';
            for (j=0;j<=ans[i].len2-1;j++)
                fo << ans[i].c2[j];
        }
        fo <<endl;
    }
}

inline int cmp(const void *a,const void *b)
{
    int k;
    Tans *A=(Tans *)a,*B=(Tans *)b;
    k=strcmp(A->c1,B->c1);
    if (k!=0) return k;
    k=strcmp(A->c2,B->c2);
    return k;
}

void sortans()
{
    qsort(ans+1,acnt,sizeof(Tans),cmp);
    print();
}

int main()
{
    init();
    findans();
    findpair();
    sortans();
    fi.close();
    fd.close();
    fo.close();
    return 0;
}

相關日誌