Cod sursa(job #3239266)

Utilizator Allie28Radu Alesia Allie28 Data 3 august 2024 21:38:02
Problema ADN Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.67 kb
#include <fstream>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <climits>

using namespace std;

ifstream fin("adn.in");
ofstream fout("adn.out");

const int LMAX = 30005;
const int INF = 0x3f3f3f3f;

int pi[20][LMAX], dp[(1<<18)][20], cost[20][20], n, from[(1<<18)][20];
char a[20][LMAX];
bool notok[20];

void Pi(char* s, int pos) {
    int k = 0, n = strlen(s + 1);
    for (int i = 2; i <= n; i++) {
        while (k && s[k + 1] != s[i]) {
            k = pi[pos][k];
        }
        if (s[k + 1] == s[i]) k++;
        pi[pos][i] = k;
    }
}

int calc(int x, int y) {
    if (x == y) {
        return -INF;
    }
    int k = 0, m = strlen(a[y] + 1), z = strlen(a[x] + 1);
    for (int i = 1; i <= m; i++) {
        while (k && a[x][k + 1] != a[y][i]) {
            k = pi[x][k];
        }
        if (a[x][k + 1] == a[y][i]) {
            k++;
        }
        if (k == z) { //s a regasit total cuvantul x
            notok[x] = 1;
            return -INF;
        }
    }
    return k;
}

//void reconst(int mask, int nxt) {
//    if (mask) {
//        int last;
//        for (int i = 0; i < n; i++) {
//            if (dp[mask][i] + cost[i][nxt] == ans - rest) {
//                last = i;
//            }
//        }
//        rest+=cost[last][nxt];
//        reconst((mask^(1<<last)), last);
//        if ((mask&(mask - 1))) {
//            //a mai ramas un bit
//            prv = last;
//            fout<<a[prv] + 1;
//        }
//        else {
//            fout<<a[last] + 1 + cost[prv][last];
//            prv = last;
//        }
//    }
//}

//vreau sa ignor total anumite cuvinte

void reconst2(int mask, int last) {
    if (mask) {
        reconst2((mask^(1<<last)), from[mask][last]);
        if ((mask&(mask - 1)) == 0) {
            fout<<a[last] + 1;
        }
        else {
            fout<<a[last] + 1 + cost[from[mask][last]][last];
        }
    }
}


int main() {
    int i, j;
    fin>>n;
    fin.get();
    for (i = 0; i < n; i++) {
        fin.get(a[i] + 1, LMAX);
        fin.get();
        Pi(a[i], i);
    }
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            //calculez costul
            cost[i][j] = calc(j, i); //pun j la capatul lui i
        }
    }
    int mask, tot;
    tot = 0;
    for (i = 0; i < n; i++) {
        if (!notok[i]) {
            tot += (1<<i);
        }
    }
    for (i = 0; i <= tot; i++) {
        for (j = 0; j < n; j++) {
            dp[i][j] = INF;
        }
    }
    for (i = 0; (1<<i) <= tot; i++) {
        if (!notok[i]) { //daca o iau in seama
            dp[(1<<i)][i] = strlen(a[i] + 1);
        }
    }
    //vreau ca la final in masca sa ma costul maxim
    for (mask = 1; mask <= tot; mask++) {
        for (i = 0; (1<<i) <= mask; i++) {
            if ((mask&(1<<i)) && !notok[i]) {
                for (j = 0; (1<<j) <= mask; j++) {
                    if (i != j && (mask&(1<<j)) && !notok[j]) {
                        if (dp[(mask^(1<<i))][j] + strlen(a[i] + 1) - cost[j][i] < dp[mask][i]) {
                            dp[mask][i] = dp[(mask^(1<<i))][j] + strlen(a[i] + 1) - cost[j][i];
                            from[mask][i] = j;
                        }
                    }
                }
            }
        }
    }
    mask--;
    int ans = INF;
    int last;
    for (i = 0; i < n; i++) {
        if (ans > dp[mask][i]) {
            ans = dp[mask][i];
            last = i;
        }
    }
    reconst2(mask, last);
//    reconst((mask^(1<<last)), last);




    fin.close();
    fout.close();
    return 0;
}