Cod sursa(job #1576947)

Utilizator alex_HarryBabalau Alexandru alex_Harry Data 23 ianuarie 2016 00:53:28
Problema ADN Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.42 kb
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream f("adn.in");
ofstream g("adn.out");
const int NMax = 20;
const int oo = 0x3f3f3f3f;
vector <int> G[NMax],Sol;
int N,M,C[NMax][NMax],DP[262150][NMax];
pair<int,int> Link[262150][NMax];
int Len[NMax];
char Matrix[NMax][30005];
int ind,Z[2*30005];
bool Ok[NMax];
char Str[2*30005];
int Array[NMax];
void Read()
{
    f>>N;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            C[i][j]=oo;
    f.get();
    for(int i=0;i<N;i++)
    {
        f.getline(Matrix[i]+1,30005);
        Len[i]=strlen(Matrix[i]+1);
    }
}
int newPosition(int k,int start)
{
    int result=0;
    while(Str[start]==Str[k] && k<=ind)
    {
        result++;
        start++;
        k++;
    }
    return result;
}

void precalcZ()
{
    int i;
    Z[1]=ind;
    int L=0,R=0;
    for(int k=2;k<=ind;k++)
    {
        if(k>R)
        {
            Z[k]=newPosition(k,1);
            L=k;R=k+Z[k]-1;
        }
        else
        {
            int aux=k-L+1;
            if(Z[aux]<R-k+1)
                Z[k]=Z[aux];
            else
            {
                int poz=R+1+newPosition(R+1,R-k+2);
                Z[k]=poz-k;R=poz-1;L=k;
            }
        }
    }
}
void eliminate()
{
    for(int i=0;i<N;i++)
        Ok[i]=1;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
        {
            if(i==j)
                continue;
            ind=0;
            for(int k=1;k<=Len[i];k++)
                Str[++ind]=Matrix[i][k];
            for(int k=1;k<=Len[j];k++)
                Str[++ind]=Matrix[j][k];
            precalcZ();
            for(int k=Len[i]+1;k<=ind;k++)
                if(Z[k]>=Len[i])
                {
                    Ok[i]=0;
                    break;
                }
            if(Ok[i]==0)
                break;
        }
    int cnt=0;
    for(int i=0;i<N;i++)
        if(Ok[i]==1)
            Array[cnt++]=i;
    N=cnt;
}
void precalcC()
{
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
        {
            if(i==j)
                continue;
            ind=0;
            for(int k=1;k<=Len[Array[j]];k++)
                Str[++ind]=Matrix[Array[j]][k];
            for(int k=1;k<=Len[Array[i]];k++)
                Str[++ind]=Matrix[Array[i]][k];
            precalcZ();
            int number=0;
            for(int k=ind-Len[Array[j]]+2;k<=ind;k++)
                if(Z[k]+k-1==ind)
                {
                    number=ind-k+1;
                    break;
                }
                C[i][j]=Len[Array[j]]-number;
        }
}

void Solve()
{
    for(int i=1;i<(1<<N);i++)
        for(int j=0;j<N;j++)
            DP[i][j]=oo;
  for(int i=0;i<N;i++)
    DP[(1<<i)][i]=Len[Array[i]];
  for(int conf=1;conf<(1<<N);conf++)
        for(int i=0;i<N;i++)
            {
                if(DP[conf][i]!=oo)
                    continue;
                if((conf & (1<<i)))
                    for(int j=0;j<N;j++)
                        {
                            if(i==j)
                                continue;
                            int Vecin=j;
                           if((conf & (1<<Vecin)))
                            if(DP[conf][i]>DP[conf^(1<<i)][Vecin]+C[Vecin][i])
                           {
                               DP[conf][i]=DP[conf^(1<<i)][Vecin]+C[Vecin][i];
                               Link[conf][i]=make_pair((conf^(1<<i)),Vecin);
                           }
                        }
            }
        int Min=oo,point=0;
        int a=(1<<N)-1;
        for(int i=0;i<N;i++)
            if(DP[a][i]<Min)
            {
                Min=DP[a][i];
                point=i;
            }
        int b=point;
        Sol.push_back(b);
        while(Link[a][b]!=make_pair(0,0))
        {
            int x=a,y=b;
            a=Link[x][y].first;b=Link[x][y].second;
            Sol.push_back(b);
        }
        for(int i=Sol.size()-1;i>=0;i--)
        {
            int pos=Sol[i];
            int len;
            if(i==Sol.size()-1)
                len=1;
            else
                len=Len[Array[Sol[i]]]-C[Sol[i+1]][Sol[i]]+1;
            for(int j=len;j<=Len[Array[Sol[i]]];j++)
                g<<Matrix[Array[Sol[i]]][j];
        }
        g<<"\n";
}

int main()
{
    Read();
    eliminate();
    precalcC();
    Solve();
    return 0;
}