Cod sursa(job #923295)

Utilizator matei_cChristescu Matei matei_c Data 23 martie 2013 13:17:31
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.39 kb
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std ;

#define maxn ( 1 << 10 )
#define maxk ( 1 << 4 )
#define maxstari ( 1 << 16 )
#define inf ( 1 << 31 ) - 1

vector<int> graf[maxn] ;

int celule[maxk] ;
int dist[maxn] ;

int grafc[maxn][maxn] ;
int grafd[maxn][maxn] ;

int cost[maxk][maxk][maxk] ;
int din[maxstari][maxk] ;

int n, m, k ;
int num ;

bool cmp(const int &a, const int &b)
{
    return dist[a] > dist[b] ;
}

void dijkstra(int nod, int num)
{
    int heap[maxn] ;

    for(int i = 1; i <= n; ++i )
        dist[i] = inf ;

    memset( heap, 0, sizeof( heap ) ) ;

    heap[0] = 1 ;
    heap[1] = nod ;
    dist[nod] = 0 ;

    while( heap[0] )
    {
        nod = heap[1] ;
        pop_heap( heap + 1, heap + heap[0] + 1, cmp ) ;
        --heap[0] ;

        for(size_t i = 0; i < graf[nod].size(); ++i )
        {
            int nod_act = graf[nod][i] ;

            if( dist[nod_act] > dist[nod] + ( num + 1 ) * grafc[nod][nod_act] && num <= grafd[nod][nod_act] )
            {
                dist[nod_act] = dist[nod] + ( num + 1 ) * grafc[nod][nod_act] ;
                heap[ ++heap[0] ] = nod_act ;
                push_heap( heap + 1, heap + heap[0] + 1, cmp ) ;
            }
        }
    }
}

void citire()
{
    scanf("%d%d%d", &k, &n, &m);

    celule[0] = 1 ;

    for(int i = 1; i <= k; ++i )
        scanf("%d", &celule[i]);

    while( m-- )
    {
        int x, y ;

        scanf("%d%d", &x, &y);

        scanf("%d%d", &grafc[x][y], &grafd[x][y]);

        grafc[y][x] = grafc[x][y] ;
        grafd[y][x] = grafd[x][y] ;

        graf[x].push_back( y ) ;
        graf[y].push_back( x ) ;
    }
}

void init_dinamica(int limstari)
{
    for(int i = 0; i < limstari; ++i )
        for(int j = 0; j <= k; ++j )
            din[i][j] = inf ;
}

void init_cost()
{
    memset( cost, -1, sizeof( cost ) ) ;

    for(int i = 0; i < k; ++i )
    {
        for(int j = 0; j <= k; ++j )
        {
            dijkstra( celule[j], i ) ;

            for(int u = 1; u <= k; ++u )
                if( dist[ celule[u] ] < inf )
                    cost[i][j][u] = dist[ celule[u] ] ;
        }
    }
}

void afla_num(int x)
{
    while( x )
    {
        if( x & 1 )
            ++num ;
        x >>= 1 ;
    }
}

void rezolva_dinamica(int limstari)
{
    din[0][0] = 0 ;

    for(int stare = 0; stare < limstari; ++stare )
    {
        num = 0;

        afla_num( stare ) ;

        for(int nod = 0; nod <= k; ++nod )
            if( din[stare][nod] < inf )
                for(int i = 1; i <= k; ++i )
                    if( ( stare & ( 1 << ( i - 1 ) ) ) == 0 && din[ stare + ( 1 << ( i - 1 ) ) ][i] > din[stare][nod] + cost[num][nod][i] && cost[num][nod][i] >= 0 )
                        din[ stare + ( 1 << ( i - 1 ) ) ][i] = din[stare][nod] + cost[num][nod][i] ;
    }
}

void afisare_sol(int stare)
{
    int sol = inf ;

    for(int i = 1; i <= k; ++i )
        sol = min( sol, din[stare][i] ) ;

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

int main()
{
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);

    citire() ;

    init_cost() ;

    int limstari = ( 1 << k ) ;

    init_dinamica( limstari ) ;

    rezolva_dinamica( limstari ) ;

    afisare_sol( limstari - 1 ) ;

    return 0 ;

}