Cod sursa(job #1736263)

Utilizator mircea_marian.popaPopa Mircea-Marian mircea_marian.popa Data 1 august 2016 14:58:33
Problema ADN Scor 50
Compilator c Status done
Runda Arhiva de probleme Marime 5.77 kb
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>

void main(){
    FILE * fi = fopen("adn.in","rt");
    unsigned char n, i, j;
    fscanf( fi, "%hhd\n" , &n);
    char secv[n][30000];
    n--;
    for( i  = 0 ; i < n ; i++ )
        fscanf(fi,"%s\n",secv[i]);
    fscanf(fi,"%s",secv[n]);
    fclose(fi);
    n++;
    unsigned short metaData[n][30000], k, len,
        jj;
    for( i = 0 ; i < n ; i++ ){
        len = strlen(secv[i]);
        metaData[i][0] = 0;
        jj=0;
        k = 1;
        while( k < len ){
            //printf("k=%d ; jj=%d \n", k , jj);
            if( secv[i][k] == secv[i][jj] ){
                jj++;
                metaData[i][k] = jj;
                k++;
            } else if( jj > 0 )
                jj = metaData[i][jj-1];
            else {
                metaData[i][k] = 0;
                k++;
            }
        }
    }
    unsigned short costs[n][n], wi, ti, lenMax,
        lenMin, startPos;
    unsigned char deElim[n], max, min;
    for( i = 0 ; i < n ; i++ )
        deElim[i] = 0;
    n--;
    for( i = 0 ; i < n ; i++ )
        for( j = i + 1 ; j <= n && !deElim[i] ; j++ )
            if( !deElim[j] ){
                if( strlen(secv[i]) > strlen(secv[j]) ){
                    max = i;
                    min = j;
                } else {
                    max = j;
                    min = i;
                }
                wi = ti = startPos = 0;
                lenMax = strlen(secv[max]);
                lenMin = strlen(secv[min]);

                while( ti < lenMax && wi < lenMin )
                    if( secv[min][wi] == secv[max][ti] ){
                        wi++;
                        ti++;
                    } else if( wi != 0){
                        wi = metaData[min][wi-1];
                        startPos = ti;
                    } else {
                        ti++;
                        startPos = ti;
                    }
                if( wi == lenMin)
                    deElim[min] = 1;
                else{
                    //TO DO calculeaza cost[max][min] si cost[min][max]
                    //max <--- min
                    costs[max][min] = lenMax - startPos;

                    //min <--- max
                    wi = startPos = 1;
                    ti = 0;
                    while( wi < lenMin ){
                        if( secv[min][wi] == secv[max][ti] ){
                            wi++;
                            ti++;
                        } else if( ti != 0 ) {
                            ti = metaData[max][ti-1];
                            startPos = wi;
                        } else {
                            wi++;
                            startPos = wi;
                        }
                    }
                    costs[min][max] = lenMin - startPos;
                }
            }
    n++;

    unsigned char indexes[n];
    for( i = 0 ; i < n ; i++ )
        indexes[i] = i;
    for( i = 0 ; i < n ; i++ )
        if( deElim[i] ){
            n--;
            for( j = i ; j < n ; j++ )
                indexes[j] = indexes[j+1];
        }
    //for( i = 0 ; i < n ; i++ )
        //printf("indexes[%d]=%d\n", i , indexes[i]);

    //ESTE BINE

    unsigned int mask, maxLen = (1<<n)-1;
    //printf("maxLen=%d\n", maxLen);
    int variante[n][maxLen];
    unsigned char parinte[n][maxLen];
    //memset((void*)variante, 0 , n*maxLen*sizeof(unsigned int));
    for( i = 0 ; i < n ; i++ )
        for( mask = 0 ; mask <= maxLen ; mask++ )
            variante[i][mask] = INT_MIN;


    //seteaza ce se stie
    for( i = 0 ; i < n ; i++ ){
        for( j = 0 ; j < i ; j++ ){
            variante[i][(1<<i)+(1<<j)] = costs[indexes[i]][indexes[j]];
            parinte[i][(1<<i)+(1<<j)] = j;
        }
        for( j = i+1 ; j < n ; j++ ){
            variante[i][(1<<i)+(1<<j)] = costs[indexes[i]][indexes[j]];
            parinte[i][(1<<i)+(1<<j)] = j;
        }
    }


    for( mask = 0 ; mask <= maxLen ; mask ++ )
        for( i = 0 ; i < n ; i++ )
            if( mask & ( 1 << i ) )
                for( j = 0 ; j < n ; j++ )
                    if( ( mask & ( 1 << j ) ) &&
                            variante[j][mask ^ ( 1 << i )] != INT_MIN &&
                            variante[i][mask] < costs[indexes[i]][indexes[j]] +
                            variante[j][mask ^ ( 1 << i )] ){
                        variante[i][mask] = costs[indexes[i]][indexes[j]] +
                            variante[j][mask ^ ( 1 << i )];
                        parinte[i][mask] = j;
                    }

    mask = variante[0][maxLen];
    j = 0;
    for( i = 1 ; i < n ; i++ )
        if( variante[i][maxLen] > mask ){
            mask = variante[i][maxLen];
            j = i;
        }


    mask = maxLen;
    ti = 0;
    fi = fopen("adn.out","wt");
    for( i = 0 ; i < n ; i++ ){
        //printf("%s (%d) ", secv[indexes[j]] + deElim[1] , indexes[j]);
        fprintf(fi,"%s", secv[indexes[j]] + ti );
        deElim[0] = j;
        j = parinte[j][mask];

        ti = costs[indexes[deElim[0]]][indexes[j]];

        mask -= (1 << deElim[0]);
    }
    //printf("\n");
    fclose(fi);



    /*for( i = 0 ; i < n ; i++ ){
        printf("%d: ", i );
        for( k = 0 ; k < strlen(secv[i]) ; k++ )
            printf("%c ", secv[i][k] );
        printf("\n");
        printf("%d: ", i );
        for( k = 0 ; k < strlen(secv[i]) ; k++ )
            printf("%d ", metaData[i][k] );
        printf("\n");
    }*/
    /*printf("deElim:\n");
    for( i = 0 ; i < n ; i++ )
        printf("%d ", deElim[i]);
    printf("\ncosts:\n");
    for( i = 0 ; i < n ; i++ ){
        for( j = 0 ; j < n ; j++ )
            if( i == j )
                printf("null\n");
            else{
                printf("<( %s ; %s ) | %d >\n", secv[i], secv[j], costs[i][j]);
            }
        printf("\n");
    }*/
}