Cod sursa(job #1638986)

Utilizator iulian_f2kGuraliuc Iulian iulian_f2k Data 8 martie 2016 10:27:23
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.78 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <queue>
#define INF ( (1 << 30) - 1)
#define NMAX 2005
using namespace std;

vector < pair < int, int> > G[NMAX];                                //Graful memorat prin liste de adiacenta. second = costul
vector<int>k;                                                       //Vectorul ce contine toti ubuntzeii, + nodul 1 si nodul N
vector<int> dist[NMAX];                                             //Vectorul cu distante. Se va calcula doar pentru nodul 1 si ubuntzei
vector<int> D[18];                                                  //D[ultNod][conf] = costul drumului pana la ultNod, drum ce contine
int N, M, K;                                                        //nodurile din configuratie

void initializare();
void bellmanFord(int nodStart);
int memoizare(int nod, int conf);

int main()
{
    initializare();
    for(int i=0; i<k.size()-1; ++i)                                 //BellmanFord-ul se face pentru toate nodurile din vector, exceptie nodul N
        bellmanFord(k[i]);

    for(int i=0; i<=K+2; ++i)
        D[i].assign(1<<(K+3), INF);                                 //Initializarea costurilor drumurilor
    cout<<memoizare(k.size()-1, (1<<K)-1)<<'\n';                    //Rezultatul se afla in D[K+1][111...11]. Mai exact drumul se termina cu
    return 0;                                                       //nodul N si contine toate elementele din vectorul cu ubuntzei.
}
int memoizare(int ultNod, int conf)                                 //IMPORTANT: Configurtia nu contine ultimul nod niciodata
{
    if(D[ultNod][conf] < INF)                                       //Daca s-a calculat deja
        return D[ultNod][conf];
    if(conf == 0)                                                   //Daca drumul nu are nici un nod
        return dist[1][k[ultNod]];                                  //Se returneaza costul de la nodul 1 la nodul ultNod
    for(int i=1; i<=K; ++i)                                         //Se incearca imbunatatirea unei muchii (ubuntzei, ultNod)
    {
        int val = INF;
        if((conf<<(i-1)) & 1) {                                     //Configuratie actuala contine al i-lea ubuntzei
            val = memoizare(i, conf - (1<<(i-1)));                  //Se considera ultimul nod i, configuratia necontinandu-l inca
            val += dist[i][k[ultNod]];                              //Costului drumului pana la i se adauga dist de la i la ultimul nod
        }
        if(val < D[ultNod][conf])                                   //Se doreste obtinerea minimului
            D[ultNod][conf] = val;
    }
    return D[ultNod][conf];
}
void bellmanFord(int nodStart)
{
    int nod, vec, d, dvec;
    queue<int>Q;
    vector<bool>inQueue;
    inQueue.assign(N+2, 0);
    dist[nodStart].assign(N+2, INF);
    dist[nodStart][nodStart] = 0;
    Q.push(nodStart);
    while(!Q.empty())
    {
        nod = Q.front();
        Q.pop();
        d = dist[nodStart][nod];
        for(int i=0; i<G[nod].size(); ++i)
        {
            vec = G[nod][i].first;
            dvec = G[nod][i].second;
            if(d + dvec < dist[nodStart][vec]) {
                dist[nodStart][vec] = d + dvec;
                if(!inQueue[vec])
                    Q.push(vec);
            }
        }
    }
}
void initializare()
{
    freopen("ubuntzei.in", "rt", stdin);
    freopen("ubuntzei.out", "wt", stdout);
    int ubu, x, y, c;
    scanf("%d%d%d", &N, &M, &K);
    k.push_back(1);
    for(int i=1; i<=K; ++i) {
        scanf("%d", &ubu);
        k.push_back(ubu);
    }
    k.push_back(N);
    for(int i=1; i<=M; ++i) {
        scanf("%d%d%d", &x, &y, &c);
        G[x].push_back(make_pair(y, c));
        G[y].push_back(make_pair(x, c));
    }
}