Usaco Training Section 4.3 Letter Game

a~z各赋一个数值(自己看图),给你一个字典(40000个单词),再给你一些字母,从中选几个组成一个或两个单词,使和最大。

最直接的想法就是n^2枚举单词,但n=40000,肯定要炸。

然后我就想到可以构造,从这些字母中选几个,再把选出的字母分成两堆,全排列一下。这个看起来挺靠谱的,因为最多只有7个字母。

于是我就开始暴力取、分、排……一下搞了100多行,一测,把样例水过了。一交,wa……原来答案排序时没有特判空串,改了就过了,竟然跑得还挺快的!

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 2147483647
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define pss pair<string,string>
using namespace std;

inline int read(){
    int x=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}

map<string,bool> m;
int tim[30],b[10],c[10],ti[30];
char a[10],a2[10],a1[10];
int sc[27]={0,2,5,4,4,1,6,5,5,1,7,6,3,5,2,3,5,7,2,1,2,4,6,6,7,5,7};
int main()
{
    ios::sync_with_stdio(false);
    freopen("lgame.in","r",stdin);
    freopen("lgame.out","w",stdout);
    string s;
    cin>>s;
    int n=s.length();
    s=' '+s;
    fclose(stdin);
    for(int i=1;i<=n;++i) ++tim[s[i]-96];
    freopen("lgame.dict","r",stdin);
    string str;
    cin>>str;
    while(str!="."){
        m[str]=1;
        cin>>str;
    }
    for(int i=1;i<=n;++i) b[i]=0;
    int maxv=0;
    set<pss> ans;
    while(b[0]==0){
        int t=0;
        for(int i=1;i<=n;++i)
            if(b[i]==1) a[++t]=s[i];
        for(int i=0;i<=t;++i) c[i]=0;
        while(c[0]==0){
            int t1=0,t2=0;
            for(int i=1;i<=t;++i)
                if(c[i]) a1[++t1]=a[i];
                else a2[++t2]=a[i];
            sort(a1+1,a1+t1+1);
            do{
                string s1="";
                for(int i=1;i<=t1;++i) s1+=a1[i];
                if(s1!=""&&!m[s1]) continue;
                sort(a2+1,a2+t2+1);
                do{
                    string s2="";
                    for(int i=1;i<=t2;++i) s2+=a2[i];
                    if(s2!=""&&!m[s2]) continue;
                    if(s1>s2) continue;
                    for(int i=1;i<=26;++i) ti[i]=0;
                    bool f=1;
                    int sum=0;
                    for(int i=1;i<=t1;++i){
                        int x=a1[i]-96;
                        ++ti[x];
                        if(ti[x]>tim[x]){f=0;break;}
                        sum+=sc[x];
                    }
                    if(!f) continue;
                    for(int i=1;i<=t2;++i){
                        int x=a2[i]-96;
                        ++ti[x];
                        if(ti[x]>tim[x]){f=0;break;}
                        sum+=sc[x];
                    }
                    if(f){
                        if(sum>maxv){
                            maxv=sum;
                            ans.clear();
                            if(s1=="") swap(s1,s2);
                            ans.insert(mp(s1,s2));
                        }
                        else if(sum==maxv){
                            if(s1=="") swap(s1,s2);
                            ans.insert(mp(s1,s2));
                        }
                    }
                }while(next_permutation(a2+1,a2+t2+1));
            }while(next_permutation(a1+1,a1+t1+1));
            int x=t;
            while(c[x]==1) c[x]=0,--x;
            c[x]=1;
        }
        int x=n;
        while(b[x]==1) b[x]=0,--x;
        b[x]=1;
    }
    cout<<maxv<<'\n';
    while(!ans.empty()){
        pss tmp=*ans.begin();ans.erase(ans.begin());
        if(tmp.second=="") cout<<tmp.first<<'\n';
        else cout<<tmp.first<<' '<<tmp.second<<'\n';
    }
    return 0;
}

4.3刷完了,继续加油!

猜你喜欢

转载自blog.csdn.net/qq_36911709/article/details/82225695