Pagini recente » Cod sursa (job #1956254) | Cod sursa (job #437806) | Cod sursa (job #2121662) | Cod sursa (job #529715) | Cod sursa (job #3278238)
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");
const int MAX2 = 32768; // 2^15 (Avem 15 orase importante)
int N,M,K;
vector<int> interestPoints(20); // Punctele mele importante
vector<vector<pair<int,int> > > graph(2005, vector<pair<int,int> >()); // Graful
vector<vector<int> > dist(20, vector<int>(2005, 1e9)); // Distantele dintre oricare 2 puncte importante (start, c1, c2, ..,cn, final)
vector<vector<int> > dp(MAX2, vector<int>(20, 1e9)); // dp[mask][i] = distanta minima de a trece prin toate orasele din mask si a ajunge la nodul i
void DIJKSTRA(int node, int index) {
// Este un DIJKSTRA normal pentru calcularea distantelor minime
priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > pq; // PQ de minime
pq.push({0, node});
dist[index][node] = 0;
while(!pq.empty()) {
int currentDistance = pq.top().first;
int currentNode = pq.top().second;
pq.pop();
if(currentDistance > dist[index][currentNode])
continue;
for(auto neighbor : graph[currentNode]) {
int cost = neighbor.first;
int vecin = neighbor.second;
int newCost = currentDistance + cost;
if(newCost < dist[index][vecin]) {
dist[index][vecin] = newCost;
pq.push({newCost, vecin});
}
}
}
}
void MIN_PATH() {
// DP-ul va tine numai orasele pe care trebuie sa le vizitez. Astfel orasul i este defapt interestPoints[i+1]
for(int i=0; i<K; i++) {
dp[1 << i][i] = dist[0][interestPoints[i+1]]; // Distanta de a trece printr-un oras si de a ramane la el, este chiar distanta calculata de la Cluj la oras din DIJKSTRA
}
for(int mask=0; mask < (1 << K); mask++) { // Incerc toate combinatiile posibile de a vizita orasele
for(int i=0; i<K; i++) {
if(mask & (1 << i)) { // Daca sunt la un oras activ, vizitat
for(int j=0; j<K; j++) {
if(!(mask & (1 << j))) { // Ma uit la un vecin care nu este deja vizitat
int new_mask = mask|(1<<j);
dp[new_mask][j] = min(dp[new_mask][j], dp[mask][i] + dist[i+1][interestPoints[j+1]]); // Daca pot ajunge la vecinul lui (j) printr-un traseu mai bun
}
}
}
}
}
int ans = 1e9;
int MAX = (1<<K)-1;
// Vizitarea optima a tuturor oraselor se va termina sigur intr-un oras specific, dar nu stim in care
for(int i=0; i<K; i++) {
ans = min(ans, dp[MAX][i] + dist[i+1][N]); // Testam fiecare posibilitate in care sa ne fi oprit si o luam pe cea mai buna
}
fout << ans;
// Sper ca v-a fost de folos. Este o problema destul de dificila. Mi-am batut si eu destul capul la ea.
// #SPOR la codare :)
}
int main() {
fin >> N >> M >> K;
for(int i=1; i<=K; i++) {
fin >> interestPoints[i];
}
interestPoints[0] = 1, interestPoints[K+1] = N; // Setez nodul 1 si nodul N ca fiind puncte importante
for(int i=1; i<=M; i++) {
int x,y,w;
fin >> x >> y >> w;
graph[x].push_back({w, y});
graph[y].push_back({w, x});
}
for(int i=0; i<=K; i++) {
DIJKSTRA(interestPoints[i], i); // Apelez DIJKSTRA pentru toate punctele importante, pentru a sti distantele dintre ele
}
if(K == 0) // Daca trebuie sa ajung direct la Vama Veche
fout << dist[0][N];
else
MIN_PATH();
return 0;
}