PTA(Advanced Level)1030. Travel Plan
阿新 • • 發佈:2020-09-19
題意
找到起點和原點間的最短路徑,如果最短路徑(用distance度量)不唯一,那麼找出cost最少的那條,題目保證此種情況下是唯一的
思路
- 複習了一遍《演算法筆記》裡的最短路徑問題,終於能完整地寫出Dijkstra演算法找最短路徑問題了。
- 這一題僅僅是在Dijkstra演算法的基礎上得到的所有最短路徑中,再利用第二 個度量
cost
來進行最優路徑的選擇,方法是用dfs
,也就是利用回溯演算法遍歷所有的路徑,在路徑終點進行求和(所以要記憶路徑),採用vector
進行比較方便回溯
程式碼
#include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; const int MAXV = 510; const int INF = 1000000000; int grid[MAXV][MAXV]; int cost[MAXV][MAXV]; int dis[MAXV]; bool vis[MAXV] = {false}; vector<int> pre[MAXV]; vector<int> tmpPath, path; int min_cities = INF, min_cost = INF; int cities, highways, st, ed; int get_min_index() { int min_value = INF, min_index = -1; for(int i=0;i<cities;i++) { if(!vis[i] && dis[i] < min_value) { min_value = dis[i]; min_index = i; } } return min_index; }//返回dis[]中最小的索引 void Dijkstra() { fill(dis, dis + MAXV, INF); dis[st] = 0; for(int cnt=0;cnt<cities;cnt++) { int u = get_min_index(); if(u == -1) return; vis[u] = true; for(int v=0;v<cities;v++) { if(!vis[v] && grid[u][v] != INF) { if(dis[u] + grid[u][v] < dis[v]) { dis[v] = dis[u] + grid[u][v]; pre[v].clear(); //pre[v]={}表示結點v的最短路徑的所有可能前驅 pre[v].emplace_back(u); }else if(dis[u] + grid[u][v] == dis[v]){ pre[v].emplace_back(u); } } } } } void dfs(int cur) { if(cur == st) //已經找到其中一條dis最小的路徑 { tmpPath.emplace_back(cur); int sum = 0; for(int i=1;i<tmpPath.size();i++) { sum += cost[tmpPath[i-1]][tmpPath[i]]; } if(sum < min_cost) //進行選優 { min_cost = sum; min_cities = tmpPath.size(); path = tmpPath; //找到符合的路徑要儲存,之後是要輸出的 } tmpPath.pop_back(); } tmpPath.emplace_back(cur); for(int i=0;i<pre[cur].size();i++) dfs(pre[cur][i]); tmpPath.pop_back(); } int main() { cin >> cities >> highways >> st >> ed; fill(grid[0], grid[0] + MAXV*MAXV, INF); int u, v; for(int i=0;i<highways;i++) { cin >> u >> v; cin >> grid[u][v]; grid[v][u] = grid[u][v]; cin >> cost[u][v]; cost[v][u] = cost[u][v]; } Dijkstra(); dfs(ed); for(int i=path.size()-1;i>=0;i--) { cout << path[i] << " "; } cout << dis[ed] << " " << min_cost << endl; return 0; }