Cod sursa(job #2340113)

Utilizator BiancaMariaVulsanVulsan Bianca Maria BiancaMariaVulsan Data 9 februarie 2019 19:50:32
Problema Ubuntzei Scor 75
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.6 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <cstring>
#define nmax 2005
#define kmax 20
#define inf 1e9
using namespace std;
ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");
int n,m,k, c[kmax], s[nmax], dist[nmax][nmax];
vector < pair<int,int> > v[nmax];
priority_queue < pair <int,int> > pq;
int dp[1<<kmax][kmax];

void citire()
{
    int i,j, x,y,cs;
    f>>n>>m>>k;
    for(i=1; i<=k; i++)
        f>>c[i];
    for(i=1; i<=m; i++)
    {
        f>>x>>y>>cs;
        v[x].push_back({y,cs});
        v[y].push_back({x,cs});
    }
}

void dijkstra(int nod, int d[])
{
    int i, pos, cst, next,val;
    for(i=1; i<=n; i++)
        d[i]=inf;
    d[nod]=0;
    pq.push({0,nod});
    while(!pq.empty())
    {
        pos=pq.top().second;
        cst=pq.top().first;
        pq.pop();
        if(s[pos]==0)
        {
            s[pos]=1;
            for(i=0; i<v[pos].size(); i++)
            {
                next=v[pos][i].first;
                val=v[pos][i].second;
                if(d[next]>d[pos]+val)
                {
                    d[next]=d[pos]+val;
                    pq.push({-d[next], next});
                }
            }
        }
    }
}



int main()
{
    int i,j,l;
    citire();
    for(i=1; i<=n; i++)
    {
        memset(s,0,sizeof(s));
        dijkstra(i, dist[i]);
    }

    if(k==0)
        g<<dist[1][n];
    else
    {
        for(i=1; i<(1<<k); i++)
            for(j=1; j<=n; j++)
            dp[i][j]=inf;
        // 1 << (i-1) repr orasul c[i];
        //initializez drumul de la 1 pana la orasul i care trece doar prin orasul i cu drumul minim de la 1 la orasul i
        for(i=1; i<=k; i++)
            dp[1 << (i-1)][i]=dist[1][c[i]];

        for(i=1; i<(1<<k); i++)
        {
            for(j=1; j<=k; j++)
            {
                if(i & (1<<(j-1))) // daca orasul j e deja vizitat cand ajung in i
                {
                    for(l=1; l<=k; l++)//vad din care oras pot ajunge in j cu un drum de cost min
                    {
                       if(l==j) continue;
                       if(i & (1<<(l-1))) // daca si orasul l e vizitat
                       // actualizez distanta pana la j cand trece prin toate loc din i
                            dp[i][j]=min(dp[i][j], dp[i ^ (1<<(j-1))][l]+dist[c[l]][c[j]]);
                    }
                }
            }
        }
        int ans = inf;
            for(i=1; i<=k; i++)
                ans=min(ans, dp[(1<<k)-1][i]+dist[c[i]][n]);
       g<<ans;
    }

    f.close();
    g.close();
    return 0;
}