Cod sursa(job #1096355)

Utilizator andreiiiiPopa Andrei andreiiii Data 1 februarie 2014 21:47:51
Problema ADN Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 kb
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#define PII pair<int, int>
#define mp make_pair
#define x first
#define y second
#define zs(x) ((x)&(x-1))

using namespace std;

const int N=20, M=30010, INF=0x3f3f3f3f;

char a[N][M];
int pi[N][M], b[N][N], c[N][N], dp[1<<19][20], nxt[1<<19][20], v[1<<19][20], nr[N];
int sz[N];

int main()
{
    freopen("adn.in", "r", stdin);
    freopen("adn.out", "w", stdout);
    int n, m, i, j, k, p, sol=INF, soli, x;
    scanf("%d\n", &n);
    for(i=1;i<=n;i++)
    {
        fgets(a[i]+1, M, stdin);
        sz[i]=strlen(a[i]+1)-1;
        a[i][sz[i]+1]='\0';
        for(j=2, k=0;j<=sz[i];j++)
        {
            while(k&&a[i][j]!=a[i][k+1]) k=pi[i][k];
            if(a[i][j]==a[i][k+1]) k++;
            pi[i][j]=k;
        }
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(i==j) continue;
            for(p=1, k=0;p<=sz[i];p++)
            {
                while(k&&a[i][p]!=a[j][k+1]) k=pi[j][k];
                if(a[i][p]==a[j][k+1]) k++;
                if(k==sz[j]) b[i][j]=1;
            }
            c[i][j]=k;
        }
    }
    for(i=2;i<(2<<n);i+=2)
    {
        for(j=1;j<=n;j++)
        {
            dp[i][j]=INF;
        }
    }
    for(m=2;m<(2<<n);m+=2)
    {
        for(i=1;i<=n;i++)
        {
            if(!(m&(1<<i))) continue;
            if(!zs(m))
                dp[m][i]=sz[i], v[m][i]=1;
            for(x=1;x<=n;x++)
            {
                if(!(m&(1<<x)))
                {
                    if(dp[m|(1<<x)][x]>dp[m][i]+sz[x]-c[i][x])
                    {
                        dp[m|(1<<x)][x]=dp[m][i]+sz[x]-c[i][x];
                        nxt[m|(1<<x)][x]=i;
                        v[m|(1<<x)][x]=1;
                    }
                    if(b[i][x]&&dp[m][i]<dp[m|(1<<x)][i])
                    {
                        dp[m|(1<<x)][x]=dp[m][i];
                        nxt[m|(1<<x)][x]=i;
                        v[m|(1<<x)][x]=0;
                    }
                }
            }
        }
    }
    for(i=1;i<=n;i++)
    {
        if(dp[(2<<n)-2][i]<sol)
        {
            sol=dp[(2<<n)-2][i];
            soli=i;
        }
    }
    for(m=(2<<n)-2;m;m^=(1<<p))
    {
        if(v[m][soli]) nr[++nr[0]]=soli;
        p=soli;
        soli=nxt[m][soli];
    }
    //printf("%d\n", *min_element(dp[(2<<n)-2]+1, dp[(2<<n)-2]+n+1));
    printf("%s", a[nr[nr[0]]]+1);
    for(i=nr[0]-1;i;i--)
    {
        printf("%s", a[nr[i]]+c[nr[i+1]][nr[i]]+1);
    }
}