Cod sursa(job #1002940)

Utilizator FlameingoAiordachioaei Marius Flameingo Data 29 septembrie 2013 12:33:55
Problema Bibel Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.28 kb
#include <cstdio>
#include <algorithm>
#include <cmath>
#define x first
#define y second
using namespace std;

typedef pair <int, int> point;
const int NMAX = 18, INFI = 2e9;

int cost[NMAX][NMAX], D[1 << NMAX - 1][NMAX], N[2], last[NMAX], l;
point V[2][NMAX];
bool k;

inline int square_distance (point a, point b) {

    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);

}

inline void make_cost () {

    int i, j;
    for (i = 1; i < N[k]; ++i)
        for (j = i + 1; j <= N[k]; ++j)
            cost[i][j] = cost[j][i] = square_distance (V[k][i], V[k][j]);

}

inline int closest (const int &in) { /// V[k][in] - V[!k][oricare]

    int _min = INFI, i, L = N[!k];
    for (i = 1; i <= L; ++i)
        _min = min (_min, square_distance (V[k][in], V[!k][i]) + last[i]);
    return _min;

}

inline void make_D () {

    int i, j;
    for (i = 1; i < l; ++i)
        for (j = 1; j <= N[k]; ++j)
            D[i][j] = INFI;
    for (i = 0; i < N[k]; ++i)
        D[1 << i][i + 1] = closest (i + 1);

}

inline int dynamic_2n () {

    int i, j, e, L = N[k], _min = INFI;
    for (i = 1; i < l; ++i)
        for (j = 0; j < L; ++j)
            if (i & 1 << j) {
                for (e = 0; e < j; ++e) /// in e se termina
                    if (i & 1 << e)
                        D[i][e + 1] = min (D[i][e + 1], D[i ^ 1 << e][j + 1] + cost[j + 1][e + 1]);
                for (e = j + 1; e < L; ++e)
                    if (i & 1 << e)
                        D[i][e + 1] = min (D[i][e + 1], D[i ^ 1 << e][j + 1] + cost[j + 1][e + 1]);
            }
    for (i = 1; i <= L; ++i)
        _min = min (_min, D[l - 1][i]),
        last[i] = D[l - 1][i];
    return _min;

}

int main () {

    freopen ("bibel.in", "r", stdin);
    freopen ("bibel.out", "w", stdout);
    int a, b;
    char t;
    N[!k] = 1;
    for (; ; ) {
        scanf ("%d", &t);
        if (!t) {
            scanf ("%d%d", &a, &b);
            V[k][++N[k]] = make_pair (a, b);
            continue;
        }
        if (t == 1) {
            l = 1 << N[k];
            make_cost ();
            make_D ();
            printf ("%d\n", dynamic_2n ());
            k = !k;
            N[k] = 0;
            continue;
        }
        break;
    }

}