Cod sursa(job #134206)

Utilizator mgntMarius B mgnt Data 10 februarie 2008 21:45:46
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.18 kb
#include <cstdio>  
using namespace std ;  

int main ( ) {  
  int const MAXN = 17 ;  
  int const MAXM = 30001 ;  
  int A [ MAXN ] [ MAXM ], lenA [ MAXN ], Prefix [ MAXN ] [ 1 + MAXM ], match [ MAXN ] [ MAXN ] ,  
      vertexLabel [ MAXN ] , edgeCost [ MAXN ] [ MAXN ] , n , ch , i, j, k, t , numVertices,  
      numVertexSet , maxHamPathCost [ MAXN ] [ 1 << MAXN ] ;  
  bool notPart [ MAXN ] ;
  bool isCharacter ;  
  FILE * io ;  
  io = fopen ( "adn.in", "r" ) ;  
  fscanf ( io , "%d\n" , & n ) ;  
  for ( i = 0 ; i < n ; i ++ ) {  
    lenA [ i ] = 0 ;  
    do {  
      ch = fgetc ( io ) ;  
      isCharacter = ( '\n' != ch ) ;  
      if ( isCharacter ) {  
        A [ i ] [ lenA [ i ] ] = ch ;  
        ++ lenA [ i ] ;  
      }  
    } while ( isCharacter ) ;  
  }  
  fclose ( io ) ;  
  /* compute string intersections using KMP */
  for ( i = 0 ; i < n ; i ++ ) {  
    Prefix [ i ] [ 1 ] = 0 ;  
    k = 0 ;  
    for ( j = 2 ; j <= lenA [ i ] ; j ++ ) {  
      while ( 0 < k && A [ i ] [ k ] != A [ i ] [ -1 + j ] ) {  
        k = Prefix [ i ] [ k ] ;  
      }  
      if ( A [ i ] [ k ] == A [ i ] [ -1 + j ] ) {  
        ++ k ;  
      }  
      Prefix [ i ] [ j ] = k ;  
    }  
  }  
  for ( i = 0 ; i < n ; i ++ ) {  
    notPart [ i ] = true ;
    for ( j = 0 ; j < n && notPart [ i ] ; j ++ ) {  
      if ( i != j && notPart [ j ] ) {  
        k = 0 ;  
        for ( t = 1 ; t <= lenA [ j ] && notPart [ i ] ; t ++ ) {  
          while ( 0 < k && A [ i ] [ k ] != A [ j ] [ -1 + t ] ) {  
            k = Prefix [ i ] [ k ] ;  
          }  
          if ( A [ i ] [ k ] == A [ j ] [ -1 + t ] ) {  
            ++ k ;  
          }  
          if ( lenA [ i ] == k ) {  
            notPart [ i ] = false ;  
            -- k ;  
          }  
        }  
        if ( notPart [ i ] ) {  
          match [ j ] [ i ] = k ;  
        }  
      }  
    }  
  }  
  /* hamiltonian path of maximum cost */
  numVertices = 0 ;  
  for ( i = 0 ; i < n ; i ++ ) {  
    if ( notPart [ i ] ) {  
      vertexLabel [ numVertices ] = i ;  
      ++ numVertices ;  
    }  
  }  
  for ( i = 0 ; i < numVertices ; i ++ ) {  
    for ( j = 0 ; j < numVertices ; j ++ ) {  
      edgeCost [ i ] [ j ] = match [ vertexLabel [ i ] ] [ vertexLabel [ j ] ] ;  
    }  
  }  
  numVertexSet = 1 << numVertices ;  
  for ( j = 0; j < numVertices ; j ++ ) {  
    maxHamPathCost [ j ] [ 1 << j ] = 0 ;  
  }  
  for ( i = 1 ; i < numVertexSet ; i ++ ) {  
    for ( j = 0 ; j < numVertices ; j ++ ) {  
      if ( 0 != ( i & ( 1 << j ) ) ) {  
        if ( 0 == ( i & ~ ( 1 << j ) ) ) {  
          maxHamPathCost [ j ] [ i ] = 0 ;  
        } else {  
          int maxValue = 0 , value ;  
          for ( t = 0 ; t < numVertices ; t ++ ) {  
            if ( j != t && 0 != ( i & ( 1 << t ) ) ) {  
              value = edgeCost [ j ] [ t ] + maxHamPathCost [ t ] [ i & ~( 1 << j ) ] ;  
              if ( maxValue < value ) maxValue = value ;  
            }  
          }  
          maxHamPathCost [ j ] [ i ] = maxValue ;  
        }  
      }  
    }  
  }  
  /* print solution */
  io = fopen ( "adn.out", "w" ) ;  
  i = numVertexSet - 1 ;  
  j = 0 ;  
  for ( t = 1 ; t < numVertices ; t ++ ) {  
    if ( maxHamPathCost [ t ] [ i ] > maxHamPathCost [ j ] [ i ] ) {  
      j = t ;  
    }  
  }  
  // print j
  for ( k = 0 ; k < lenA [ vertexLabel [ j ] ] ; k ++ ) {  
    fprintf ( io, "%c", A [ vertexLabel [ j ] ] [ k ] ) ;  
  }  
  i = i & ~ ( 1 << j ) ;  
  while ( 0 != i ) {  
    bool notFound = true ;  
    for ( t = 0 ; t < numVertices && notFound ; t ++ ) {  
      if ( 0 != ( i & ( 1 << t ) ) && j != t &&  
           maxHamPathCost [ j ] [ i | ( 1 << j ) ] == edgeCost [ j ] [ t ] +  
                                        maxHamPathCost [ t ] [ i ] ) {
        notFound = false ;  
        ch = t ;  
      }  
    }  
    t = ch ;  
    // print j-t
    for ( k = edgeCost [ j ] [ t ] ; k < lenA [ vertexLabel [ t ] ] ; k ++ ) {  
      fprintf ( io, "%c", A [ vertexLabel [ t ] ] [ k ] ) ;  
    }  
    j = t ;  
    i = i & ~ ( 1 << j ) ;  
  }  
  fclose (io) ;  
  return 0 ;  
}