Cod sursa(job #2001317)

Utilizator Coroian_DavidCoroian David Coroian_David Data 16 iulie 2017 13:53:42
Problema Team Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.46 kb
/**
*   Problema data se poate rezolva prin dinamica + distra. (kj)
*
*   Facem dinamica bottom-up dp[i][st][dr] = costul necesar pentru ca banda din st..dr sa ajunga la destinatie.
*   Recurenta : dp[i][st][dr] = dp[aux][st][aux - 1] + dp[aux][aux + 1][dr] + distantele. (aux se latura la grupa)
*
*   Notam cu 0 discoteca.
*
*   Rezultatul se afla in dp[0][1][pers].
*
*   Time Complexity : O(P*(Nlog2N+M) + P^4);
*
*   COROIAN DAVID, Satu Mare, ROMANIA
**/

#include <cstdio>

#include <cstring>

#define sqrInf 999999999

using namespace std;

FILE *f, *g;

int pers, n, m;

int dest[59];

int d[509][509];

int dp[59][59][59];

int drum[59][509];

int h[509];

int poz[509];

int nods;

int k;

int lst[509];

int urm[250000];
int nod[250000];

void add(int a, int b)
{
    k ++;

    nod[k] = b;
    urm[k] = lst[a];

    lst[a] = k;
}

inline int mna(int a, int b)
{
    return (a < b ? a : b);
}

void readFile()
{
    f = fopen("team.in", "r");

    fscanf(f, "%d", &pers);
    fscanf(f, "%d", &n);
    fscanf(f, "%d", &m);

    int i, j;
    int a, b, c;

    for(i = 1; i <= n; i ++)
    {
        for(j = i + 1; j <= n; j ++)
            d[i][j] = d[j][i] = sqrInf;
    }

    for(i = 1; i <= m; i ++)
    {
        fscanf(f, "%d%d%d", &a, &b, &c);

        if(d[a][b] == sqrInf)
        {
            add(a, b);
            add(b, a);
        }

        d[a][b] = d[b][a] = mna(d[a][b], c);
    }

    for(i = 1; i <= pers; i ++)
    {
        fscanf(f, "%d", &dest[i]);
    }

    fclose(f);
}

void swapp(int &a, int &b)
{
    int aux = a;
    a = b;
    b = aux;
}

void schimba(int a, int b)
{
    swapp(h[a], h[b]);
    swapp(poz[h[a]], poz[h[b]]);
}

bool cmp(int a, int b, int dp[])
{
    return (dp[h[a]] < dp[h[b]]);
}

void upHeap(int poz, int dp[])
{
    while(poz > 1)
    {
        if(cmp(poz, poz / 2, dp) == 1)
        {
            schimba(poz, poz / 2);

            poz /= 2;
        }

        else
            return;
    }
}

void downHeap(int poz, int dp[])
{
    while(poz * 2 <= nods)
    {
        int fiu = poz;

        if(poz * 2 <= nods)
        {
            if(cmp(poz * 2, fiu, dp) == 1)
                fiu = poz * 2;
        }

        if(poz * 2 + 1 <= nods)
        {
            if(cmp(poz * 2 + 1, fiu, dp) == 1)
                fiu = poz * 2 + 1;
        }

        if(fiu == poz)
            return;

        schimba(poz, fiu);
        poz = fiu;
    }
}

void adh(int i, int dp[])
{
    nods ++;

    h[nods] = i;

    poz[i] = nods;

    upHeap(nods, dp);
}

void dilit(int poz, int dp[])
{
    schimba(poz, nods);

    nods --;

    downHeap(poz, dp);
}

void distra(int a, int dp[])
{
    memset(poz, 0, sizeof(poz));
    memset(h, 0, sizeof(h));

    int p, mn, u;
    int i;
    for(i = 1; i <= n; i ++)
        dp[i] = sqrInf;

    dp[a] = 0;

    for(i = 1; i <= n; i ++)
        adh(i, dp);

    for(i = 1; i <= n; i ++)
    {
        mn = h[1];

        dilit(1, dp);

        for(p = lst[mn]; p != 0; p = urm[p])
        {
            u = nod[p];

            if(dp[u] > dp[mn] + d[mn][u])
            {
                dp[u] = dp[mn] + d[mn][u];

                upHeap(poz[u], dp);
            }
        }
    }
}

void init0()
{
    int i, j, h;
    for(i = 0; i <= pers; i ++)
    {
        for(j = 1; j <= pers; j ++)
        {
            for(h = j; h <= pers; h ++)
            {
                dp[i][j][h] = sqrInf;
            }
        }

        dp[i][i][i] = 0;
    }
}

int rez;

void solve()
{
    dest[0] = 1;

    int i;
    for(i = 0; i <= pers; i ++)
        distra(dest[i], drum[i]);

    init0();

    int j, h, l;
    int st, dr;
    for(j = 1; j <= pers; j ++)
    {
        for(h = 1; h <= pers - j + 1; h ++)
        {
            st = h;
            dr = h + j - 1;

            for(i = 0; i <= pers; i ++)
            {
                for(l = st; l <= dr; l ++)
                    dp[i][st][dr] = mna(dp[i][st][dr],
                                        dp[l][st][l - 1] + dp[l][l + 1][dr] + drum[i][dest[l]]
                                        );
            }
        }
    }

    rez = dp[0][1][pers];
}

void printFile()
{
    g = fopen("team.out", "w");

    fprintf(g, "%d\n", rez);

    fclose(g);
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}