2662. Minimum Cost of a Path With Special Roads

https://leetcode.com/problems/minimum-cost-of-a-path-with-special-roads/

這是一題 SSSP(Single-Source Shortest Path) 問題,第一個想法就是直接用 Dijkstra 解決。但是這題跟其他問題不一樣的地方在於,這個 graph 是無限大的,因爲我們要在二維平面找最短距離,而二維平面沒有邊界。因此,什麼時候要結束 Dijkstra algorithm 變成了新的問題。

首先,從 start 到 target 的最短距離只會有兩種情況,

  1. 有經過 special road
  2. 沒有經過 special road 所以只需要找到 start 到各個 special road 的終點的最短距離,最後再看看 start 到 target 的最短距離是多少即可。

同樣地,從 start 到 special road 的終點的最短距離也只會有以上的兩種情況,所以跑 Dijkstra 的時候,只需要不斷比較有無使用 special road 的 cost。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int minimumCost(vector<int>& start, vector<int>& target, vector<vector<int>>& specialRoads) {
    int n = specialRoads.size();
    vector<int> shortest(n, INT_MAX); // 記錄從 start 到第 i 個 specialRoad 終點的最短距離
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    for (int i = 0; i < n; i++){
        int x1 = specialRoads[i][0];
        int y1 = specialRoads[i][1];
        int x2 = specialRoads[i][2];
        int y2 = specialRoads[i][3];
        int cost = specialRoads[i][4];
        int with_road = abs(start[0] - x1) + abs(start[1] - y1) + cost; // 有使用 specialRoad
        int without_road = abs(start[0] - x2) + abs(start[1] - y2); // 沒有使用 specialRoad
        pq.push({min(with_road, without_road), i});
    }
    while (not pq.empty()){
        auto [distance, index] = pq.top();
        pq.pop();
        if (shortest[index] != INT_MAX){
            continue;
        }
        shortest[index] = distance;
        for (int i = 0; i < n; i++){
            if (shortest[i] != INT_MAX){
                continue;
            }
            int x1 = specialRoads[i][0];
            int y1 = specialRoads[i][1];
            int x2 = specialRoads[i][2];
            int y2 = specialRoads[i][3];
            int cost = specialRoads[i][4];
            int with_road = abs(specialRoads[index][2] - x1) + abs(specialRoads[index][3] - y1) + cost;
            int without_road = abs(specialRoads[index][2] - x2) + abs(specialRoads[index][3] - y2);
            pq.push({distance + min(with_road, without_road), i});
        }
    }
    int ans = abs(start[0] - target[0]) + abs(start[1] - target[1]);
    // 最後檢查從第 i 個 specialRoad 的終點到 target 的距離
    // 如果更短的話就更新最小值
    for (int i = 0; i < n; i++){
        ans = min(ans, shortest[i] + abs(specialRoads[i][2] - target[0]) + abs(specialRoads[i][3] - target[1]));
    }
    return ans;
}

time complexity: $O(n^2 \log n)$
space complextiy: $O(n^2)$
where n = specialRoads.size()

解完之後看了一下 leetcode discussion,發現大家的解法似乎簡單一些,但是目前還沒看懂,理解之後再更新。