Cod sursa(job #515639)

Utilizator eudanipEugenie Daniel Posdarascu eudanip Data 21 decembrie 2010 21:52:57
Problema ADN Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.78 kb
#include<stdio.h>
#include<string.h>

#define LCONF (1<<18)+4
#define INF 2000000000
#define minim(a,b) (a<b ? a : b)

int n,el[20],sol;
int d[LCONF][20];
int pred[LCONF][20];
int nr[20],c[20][20];
char s[20][30005];
int pi[20],v[20];

int kmp(int i1,int i2)
{
    int i,q=0;
    
    memset(pi,0,sizeof(pi));
    
    for(i=2;i<=nr[i2];i++)
    {
        while(q>0 && s[i2][q+1]!=s[i2][i])
            q=pi[q];
        if(s[i2][q+1]==s[i2][i])
            q++;
        pi[i]=q;
    }
    
    q=0;
    for(i=1;i<=nr[i1];i++)
    {
        while(q>0 && s[i1][i]!=s[i2][q+1])
            q=pi[q];
        if(s[i1][i]==s[i2][q+1])
            q++;
        if(q==nr[i2])
            return nr[i2];
    }
    return q;
}

// functia de aflare a costului cu KMP

void recur(int cf,int last)
{
    if(!cf)
        return ;
    v[++nr[0]]=last;
    recur(cf-(1<<(last-1)),pred[cf][last]);
}

// functia de reconstituire

int main ()
{
    int i,j,t,cf;
    freopen("adn.in","r",stdin);
    freopen("adn.out","w",stdout);
    scanf("%d\n",&n);
    for(i=1;i<=n;i++)
    {
        fgets(s[i]+1,sizeof(s[i])-1,stdin);
        nr[i]=strlen(s[i]+1);
        while(s[i][nr[i]]!='A'
        &&    s[i][nr[i]]!='C'
        &&    s[i][nr[i]]!='G'
        &&    s[i][nr[i]]!='T')
            nr[i]--;
    }
    
    // citirea
    
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            if(i==j)
                continue;
            c[i][j]=kmp(i,j);
            if(c[i][j]==nr[j])
                el[j]=1;
        }
    for(i=1;i<=n;i++)
        if(el[i])
            for(j=1;j<=n;j++)
                c[j][i]=nr[i];
                
    // calcularea costurilor
    
    for(i=1;i<(1<<n);i++)
        for(j=1;j<=n;j++)
        {
            if(!((1<<(j-1))&i))
                continue;
            cf=i-(1<<(j-1));
            if(!cf)
            {
                d[i][j]=nr[j];
                continue;
            }
            d[i][j]=INF;
            for(t=1;t<=n;t++)
            {
                if(!((1<<(t-1))&cf))
                    continue;
                if(d[cf][t]+nr[j]-c[t][j]<d[i][j])
                {
                    d[i][j]=d[cf][t]+nr[j]-c[t][j];
                    pred[i][j]=t;
                }
            }
        }

    // ciclu hamiltonian
        
    sol=INF;
    for(i=1;i<=n;i++)
        sol=minim(sol,d[(1<<n)-1][i]);
    for(i=1;i<=n;i++)
        if(d[(i<<n)-1][i]==sol)
        {
            recur((1<<n)-1,i);
            break;
        }

    // apelarea reconstituirii
    
    for(i=n;i>=1;i--)
        for(j=c[v[i+1]][v[i]]+1;j<=nr[v[i]];j++)
            printf("%c",s[v[i]][j]);
    printf("\n");

    // afisarea
    return 0;
}