记录编号 400022 评测结果 WAWWWWWWWWWWWWWWWWWW
题目名称 [SCOI 2008] 劣质编码 最终得分 5
用户昵称 Gravatar不存在的 是否通过 未通过
代码语言 C++ 运行时间 0.007 s
提交时间 2017-04-28 22:10:59 内存使用 3.34 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
typedef short BOOL;
const int N = 61;
const int _MAX = 1000000000;
int n,m,len[N];
int ans,dp[N][N][N][3];
char data[N][N];
BOOL cmp[N][N][N];
struct zht{
    int a,i,j,t;
    zht(){}
    zht(int aa,int ii,int jj,int tt):a(aa),i(ii),j(jj),t(tt){}
};
queue<zht> dui;
int scan(){
    char cc=' ';int re=0,fh=1;
    while(cc==' '||cc=='\r'||cc=='\n')cc=getchar();
    if(cc=='+'){fh=-1;cc=getchar();}
    if(cc=='+'){fh=1;cc=getchar();}
    while('0'<=cc&&cc<='9'){
        re=re*10+cc-'0';
        cc=getchar();
    }
    return re*fh;
}
int scans(char s[]){
    char cc=' ';int i;
    cc=getchar();
    for(i=1;!(cc=='\r'||cc=='\n');i++){ 
        s[i]=cc;
        cc=getchar();
    }s[i]=0;
    return i-1;
}
int main(){
	freopen("codez.in","r",stdin);
	freopen("codez.out","w",stdout);
    int i,j,k;
    n=scan();
    for(i=1;i<=n;i++){
        len[i]=scans(data[i]);
        while(data[i][len[i]]==' ')data[i][len[i]--]=0;
        if(len[i]==0){printf("0\n");return 0;}
    }
    //找出所有可以转移的位置
    //也就是判断相等 
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++){
        for(k=0;k<len[i];k++){
            int tmp=min(len[i]-k,len[j]),ii;
            for(ii=1;ii<=tmp;ii++)
                if(data[i][ii+k]!=data[j][ii]) break;
            cmp[i][j][k] = ii>tmp;
        }cmp[i][j][len[i]]=1;
    }
    for(i=0;i<=n;i++)
    for(j=0;j<N;j++)
    for(k=0;k<N;k++)
        dp[i][j][k][0]=dp[i][j][k][1]=dp[i][j][k][2]=_MAX;
    for(i=1;i<=n;i++){
        dui.push(zht(i,0,0,2));
        dp[i][0][0][2]=len[i];
    }
    ans=_MAX;
    while(!dui.empty()){
        zht now = dui.front(); dui.pop();
        int aa,ii,jj,tt,l;
        int &Dp = dp[now.a][now.i][now.j][now.t];
        //另外匹配的两个串结构不同 
        if(!now.t){
            //update ans
            if(now.i==now.j&&now.i==len[now.a]){
                if(dp[now.a][now.i][now.j][now.t]<ans)
                    ans=dp[now.a][now.i][now.j][now.t];
                continue;
            }
            //枚举新的匹配串
            for(i=1;i<=n;i++){
                /*
                    [tt.a]
                    111111111
                          1111111
                          [i]
                    转移状态 
                */
                //tt.i > tt.j
                //接到匹配位数少的那一个上 
                if(!cmp[now.a][i][now.j]) continue;tt=0;
                //如果接超了,就把新接的串当成tt.a 
                if(len[i]+now.j > len[now.a]){
                        //由于等式的传递关系,长的匹配一定可以匹配到新串i上 
                        //并且可以得到之前的串tt.a转换成的匹配一定比j长
                    aa=i;ii=len[now.a]-now.j;jj=now.i-now.j;
                    l=Dp + len[i] - (len[now.a]-now.j);
                //否则只是更新一下长度 
                }else{
                    aa=now.a;ii=now.j+len[i];jj=now.i;
                    if(jj>ii)swap(jj,ii);
                    l=Dp;
                }
                //push
                if(l < dp[aa][ii][jj][tt]){
                    dui.push(zht(aa,ii,jj,tt));
                    dp[aa][ii][jj][tt]=l;
                }
 
            }
        //模板串和匹配i串结构相同 
        }else if(now.t==1){
            //因为两个匹配结构相同,故不能更新答案 
            if(now.i==now.j&&now.i==len[now.a])continue;
            //枚举新的匹配串 
            for(i=1;i<=n;i++){
                //接到短的上 
                if(!cmp[now.a][i][now.j]) continue;
                if(now.j+len[i] >= len[now.a]){
                    //如果接超了,就把新接的串当成tt.a 
                    aa=i;ii=jj=len[now.a]-now.j;tt=2;
                    l=Dp + len[i] - ii;
                }else{
                    aa=now.a;ii=now.i;jj=now.j+len[i];tt=1;
                    l=Dp;
                }
                //push 
                if(l < dp[aa][ii][jj][tt]){
                    dui.push(zht(aa,ii,jj,tt));
                    dp[aa][ii][jj][tt]=l;
                }
            }
        //结构相同的两个匹配串
        }else if(now.t==2){
            for(i=1;i<=n;i++){
                if(!cmp[now.a][i][now.i])continue;
                //不要拿自己和自己匹配
                if(now.i==0&&i==now.a) continue;
                //一下放两个一样的 
                if(now.j+len[i] > len[now.a]){
                    aa=i;ii=len[i];jj=len[now.a]-now.j;tt=1;
                    l=Dp + len[i] - jj;
                }else{
                    aa=now.a;ii=jj=now.i+len[i];tt=2;
                    l=Dp;
                }
                //push 
                if(l < dp[aa][ii][jj][tt]){
                    dp[aa][ii][jj][tt]=l;
                    dui.push(zht(aa,ii,jj,tt));
                }
                //枚举第二个匹配串 
                for(j=1;j<=n;j++){
                    //******能接上去********
                    if(!cmp[now.a][j][now.j]) continue;
                    //两个新匹配串不能是同一个串 ,但是内容需要相同 
                    if(i==j)continue;
                    //能接上去
                    if(!cmp[i][j][0])continue;
                    int si=i,sj=j;
                    //若不相等保证 len[si] > len[sj] 
                    //若长度相等且sj==当前串 则使si==当前串 
                    if(len[sj] > len[si] || (len[si]==len[sj]&&sj==now.a)) swap(si,sj);
                    if(now.i+len[si] > len[now.a]){
                        if(now.j+len[sj] > len[now.a]){
                            aa=si;ii=len[sj];jj=len[now.a]-now.i;
                            l=Dp+ len[si]-jj;
                            tt=0;
                        }else{
                            aa=si;ii=len[now.a]-now.i;jj=len[sj];
                            l=Dp+len[si]-ii;
                            //sj和tt.a相同而si较长 仍是2状态 
                            //***我不知道为啥这里一开始填的是 if(ii==jj)
                            if(now.a==sj&&now.i==0) tt=2;
                            else tt=0;
                        }
                    }else{
                        aa=now.a;ii=now.i+len[si];jj=now.i+len[sj];tt=0;
                        l=Dp;
                        if(now.i==0&&si==now.a){
                            if(jj<len[now.a])tt=1;
                            //相等 
                            else{
                                aa=sj;ii=jj=len[sj];
                                tt=2;
                            }
                        }
                    }
                    if(l < dp[aa][ii][jj][tt]){
                        dp[aa][ii][jj][tt]=l;
                        dui.push(zht(aa,ii,jj,tt));
                    }
                }
            }
        }
    }
    if(ans==_MAX)
        printf("-1\n");
    else
        printf("%d\n",ans);
    return 0;
}