1. 程式人生 > 實用技巧 >PTA(Advanced Level)1030. Travel Plan

PTA(Advanced Level)1030. Travel Plan

題意

找到起點和原點間的最短路徑,如果最短路徑(用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;
}