Cod sursa(job #123471)

Utilizator nimicLeoveanu Mihaita Alexandru nimic Data 16 ianuarie 2008 06:00:58
Problema Bibel Scor 15
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.54 kb
#include <cstdio>
#include <string>
#include <ext/hash_map>
#define pow(x) (1u<<(x))
#define sqr(x) ((x)*(x))
#define inf (1<<30)

using namespace std;
using namespace __gnu_cxx; 

int x[20], y[20], px[20], py[20], n, nrpos;
int sol[17], dist[17][32], ok[32], Plus[20];
hash_map<int, int> memo;

void preback(int mask, int last, int cost, int nr){
     for (int i=0; i<n; i++)
         if (!(mask & pow(i))) preback(mask | pow(i), i, cost+dist[last][i], nr+1);
     if (nr==n || nr==5) return;
     if (memo.find(mask) == memo.end()) memo[mask] = inf;
     if (cost < memo[mask]) memo[mask] = cost;
}

int bound(int mask){
    if (memo.find(mask) != memo.end()) return memo[mask];
    int rez = 0;
    for (int i=0; i<n; i++)
        if (mask & pow(i)){
           int plus = inf;
           for (int j=0; j<n; j++)
               if ((mask & pow(j)) && j!=i && dist[i][j]<plus) plus = dist[i][j];
           rez += plus;
           }
    return rez;
}

void back(int now, int mask, int mai, int cost){
     if (!mai){
        if (cost < sol[now]) sol[now] = cost;
        return;
     }
     ok[now] = 1;
     int opt = inf, bun=0;
     for (int i=0; i<n; i++)
         if (!ok[i] && dist[now][i]<opt) opt=dist[now][i];
     for (int i=0; i<n; i++)
         if (!ok[i] && opt+bound(mask)<sol[i]) bun=1;
     if (bun)
        for (int i=0; i<n; i++)
            if (!ok[i]) back(i, mask-pow(i), mai-1, cost+dist[now][i]);
     ok[now] = 0;
}

void solve(){
     for (int i=0; i<n; i++)
         for (int j=0; j<n; j++)
             dist[i][j] = (sqr(x[i]-x[j]) + sqr(y[i]-y[j]));
     int best[n];
     for (int i=0; i<n; i++){
         best[i] = inf;
         for (int j=0; j<nrpos; j++)
             if (sqr(px[j]-x[i]) + sqr(py[j]-y[i]) + Plus[j]<best[i])
                best[i] = sqr(px[j]-x[i]) + sqr(py[j]-y[i]) + Plus[j];
         sol[i] = inf;
     }
     for (int i=0; i<n; i++)
         preback(pow(i), i, best[i], 1);
     for (int i=0; i<n; i++)
         back(i, pow(n)-1-pow(i), n-1, best[i]);
     nrpos = n;
     int min=sol[0];
     for (int i=0; i<n; i++){
         if (sol[i] < min) min = sol[i];
         px[i]=x[i], py[i]=y[i], Plus[i] = sol[i];
     }
     printf("%d\n", min);
     memo.clear();
     n=0;
}

int main()
{
    freopen("bibel.in", "r", stdin);
    freopen("bibel.out", "w", stdout);
    nrpos=1;
    while (1){
          int op;
          scanf("%d", &op);
          if (op==0) scanf("%d %d", x+n, y+n), n++; else
          if (op==1) solve(); else return 0;
    }
}