Cod sursa(job #1556659)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 25 decembrie 2015 16:45:39
Problema ADN Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.28 kb
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 18;
const int MAX_LEN = 30000;

int D[1 << MAX_N][MAX_N];
int F[1 << MAX_N][MAX_N];
int cost[MAX_N][MAX_N]; // cost[i][j] = costul daca j vine dupa i
char s[MAX_N][MAX_LEN + 1];
char tmp[2 * MAX_LEN + 2];
int Z[2 * MAX_LEN + 2];
int N;

int ZAlg(int A, int B)
{
    int N = strlen(s[A]), M = strlen(s[B]);

    memcpy(tmp, s[B], M);
    tmp[M] = '$';
    memcpy(tmp + M + 1, s[A], N);

    int lBox = 0, rBox = 0;

    for (int i = 1; i <= N + M; i++)
    {
        if (i <= rBox)
            Z[i] = min(Z[i - lBox], rBox - i + 1);
        else
            Z[i] = 0;

        while (tmp[Z[i]] == tmp[i + Z[i]])
            Z[i]++;
        
        if (i + Z[i] - 1 > rBox)
        {
            rBox = i + Z[i] - 1;
            lBox = i;
        }
    }

    int Q = 0;
    for (int i = 0; i < N; i++)
        Q = max(Q, Z[i + M + 1]);
    return M - Q;
}

int hamilton(int mask, int prev)
{
    if (D[mask][prev])
        return D[mask][prev];
    if (mask == (1 << N) - 1)
        return 0;
    D[mask][prev] = numeric_limits <int> :: max();
    for (int i = 0; i < N; i++)
    {
        if (((mask >> i) & 1) == false)
        {
            int C = hamilton(mask | (1 << i), i) + cost[prev][i];
            if (D[mask][prev] > C)
            {
                D[mask][prev] = C;
                F[mask][prev] = i;
            }
        }
    }
    return D[mask][prev];
}

int main()
{
    ifstream in("adn.in");
    ofstream out("adn.out");

    in >> N;
    for (int i = 0; i < N; i++)
        in >> s[i];

    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            if (i != j)
                cost[i][j] = ZAlg(i, j);

    int minCost = numeric_limits <int> :: max(), node;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < (1 << N); j++)
            for (int t = 0; t < N; t++)
                D[j][t] = 0;

        int C = strlen(s[i]) + hamilton(1 << i, i);
        if (minCost > C)
        {
            minCost = C;
            node = i;
        }
    }

    int mask = 1 << node;
    out << s[node];
    while (mask != (1 << N) - 1)
    {
        int prev = node;
        node = F[mask][node];
        out << (s[node] + strlen(s[node]) - cost[prev][node]);
        mask |= (1 << node);
    }
    out << '\n';
    return 0;
}