Cod sursa(job #3307107)

Utilizator Grama2008Grama Andrei Teodor Grama2008 Data 17 august 2025 15:37:27
Problema Gather Scor 90
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.88 kb
#include <bits/stdc++.h>

using namespace std;

const int K=15, N=755;

vector<tuple<int, int, long long>> adj[N];

int k,n,m,a,b,c,inputd;
long long dist[N],len[K][K][K+1],prisoners[K],dp[K][1<<K];

void getdist(int start, int moves){
    using state=pair<long long, int>;
    priority_queue<state, vector<state>, greater<state>>q;
    memset(dist, (1<<6)-1, sizeof(dist));
    dist[prisoners[start]]=0;
    q.push({0, prisoners[start]});
    while (!q.empty()){
        auto [d, node]=q.top();q.pop();
        if (d>dist[node]){
            continue;
        }
        for (auto [maxmoves, newnode, weight]:adj[node]){
            if (maxmoves<moves){
                continue;
            }
            if (dist[newnode]>dist[node]+weight){
                dist[newnode]=dist[node]+weight;
                q.push({dist[newnode], newnode});
            }
        }
    }
    for (int i=0;i<k;i++){
        len[start][i][moves]=dist[prisoners[i]];
    }
}

void getstartdist(){
    using state=pair<long long, int>;
    priority_queue<state, vector<state>, greater<state>>q;
    memset(dist, (1<<6)-1, sizeof(dist));
    q.push({0,1});
    dist[1]=0;
    while (!q.empty()){
        auto [d, node]=q.top();q.pop();
        if (d>dist[node]){
            continue;
        }
        for (auto [maxmoves, newnode, weight]:adj[node]){
            if (dist[newnode]>dist[node]+weight){
                dist[newnode]=dist[node]+weight;
                q.push({dist[newnode], newnode});
            }
        }
    }
}

signed main()
{
    memset(dp, (1<<6)-1, sizeof(dp));
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>k>>n>>m;
    for (int i=0;i<k;i++){
        cin>>prisoners[i];
    }
    for (int i=0;i<m;i++){
        cin>>a>>b>>c>>inputd;
        adj[a].push_back(make_tuple(inputd, b, c));
        adj[b].push_back(make_tuple(inputd, a, c));
    }
    for (int i=1;i<=n;i++){
        sort(adj[i].begin(), adj[i].end(), greater<tuple<int, int, long long>>());
    }
    for (int i=0;i<k;i++){
        for (int j=0;j<=k;j++){
            getdist(i,j);
        }
    }
    getstartdist();
    for (int i=0;i<k;i++){
        dp[i][1<<i]=dist[prisoners[i]];
    }
    int fullmask=(1<<k)-1;
    for (int mask=1;mask<=fullmask;mask++){
        int cpymask=mask;
        int cnt=__builtin_popcount(mask);
        while (cpymask){
            int i=__builtin_ctz(cpymask);
            cpymask=cpymask^(1<<i);
            int notmask=mask^fullmask;
            while (notmask){
                int j=__builtin_ctz(notmask);
                notmask=notmask^(1<<j);
                int newmask=mask|(1<<j);
                dp[j][newmask]=min(dp[j][newmask], dp[i][mask]+1LL*(1+cnt)*len[i][j][cnt]);
            }
        }
    }
    long long ans=1e18;
    for (int i=0;i<k;i++){
        ans=min(ans, dp[i][fullmask]);
    }
    cout<<ans;
    return 0;
}