Cod sursa(job #116784)

Utilizator astronomyAirinei Adrian astronomy Data 19 decembrie 2007 15:15:16
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.24 kb
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;

#define MAX_N 760
#define MAX_M 1600
#define MAX_K 16
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define PII pair<int, int>
#define INF 1000000000
#define b(x) (1<<(x))

int N, M, K, Min[MAX_K][1<<MAX_K], A[32][32][32];
int cnt[1<<MAX_K], P[MAX_K], D[MAX_N];
vector<PII> G[MAX_N];
vector<int> Lim[MAX_N];
queue<int> Q;

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

void baga(int src, int mmax)
{
    int i, j, k;

    for(i = 1; i <= N; i++) D[i] = INF;
    Q.push(src), D[src] = 0;

    while(Q.size() > 0)
    {
        j = Q.front(), Q.pop();
        for(k = 0; k < G[j].size(); k++)
         if(D[j]+G[j][k].y < D[ G[j][k].x ] && Lim[j][k] >= mmax)
            D[ G[j][k].x ] = D[j]+G[j][k].y, Q.push(G[j][k].x);
    }
}

int rec(int x, int conf)
{
    if(Min[x][conf] != -1)
        return Min[x][conf];

    int aux = x, y, conf2, ret = INF;

    if( x != 0 && (conf&b(x-1)) )
    {
        for(y = 0; y <= K; y++)
         if(x != y)
            ret = MIN(ret,
            rec(y,conf2=conf^b(x-1))+
            (A[y][x][cnt[conf2]]==INF?INF:A[y][x][cnt[conf2]]*cnt[conf2]));
    }

    return Min[x][conf] = ret;
}

void ruleaza(void)
{
    int i, j, k, a, b, c, d, res;

    scanf("%d %d %d", &K, &N, &M);

    for(P[0] = 1, i = 1; i <= K; i++) scanf("%d ", &P[i]);

    for(i = 1; i <= M; i++)
    {
        scanf("%d %d %d %d\n", &a, &b, &c, &d);
        G[a].pb( mp(b, c) ), G[b].pb( mp(a, c) );
        Lim[a].pb(d+1), Lim[b].pb(d+1);
    }
    
    for(i = 1; i < b(MAX_K); i++) cnt[i] = cnt[i>>1]+(i&1);
    for(i = 0; i < b(MAX_K); i++) cnt[i]++;

    for(i = 0; i <= K; i++)
     for(j = 1; j <= K+1; j++)
     {
        baga(P[i], j);
        for(k = 0; k <= K; k++)
            A[i][k][j] = D[P[k]];
     }

    memset(Min, -1, sizeof(Min)), Min[0][0] = 0;

    for(res = INF, i = 0; i <= K; i++)
        res = MIN(res, rec(i,b(K)-1));

    printf("%d\n", res);
}

int main(void)
{
    freopen("gather.in", "rt", stdin);
    freopen("gather.out", "wt", stdout);

    ruleaza();
    
    return 0;
}