图论 | 前往目标的最小代价

学术   科技   2023-05-25 06:02   北京  

题目(难度中等)

    给你一个数组 start ,其中 start = [startX, startY] 表示你的初始位置位于二维空间上的 (startX, startY) 。另给你一个数组 target ,其中target = [targetX, targetY] 表示你的目标位置 (targetX, targetY) 。

    从位置 (x1, y1) 到空间中任一其他位置 (x2, y2) 的代价是 |x2 - x1| + |y2 - y1| 。

    给你一个二维数组 specialRoads ,表示空间中存在的一些特殊路径。其中 specialRoads[i] = [x1i, y1i, x2i, y2i, costi] 表示第 i 条特殊路径可以从 (x1i, y1i) 到 (x2i, y2i) ,但成本等于 costi 。你可以使用每条特殊路径任意次数。

    返回从 (startX, startY) 到 (targetX, targetY) 所需的最小代价。

示例 1:

输入:start = [1,1], target = [4,5], specialRoads = [[1,2,3,3,2],[3,4,4,5,1]]

输出:5

解释:从 (1,1) 到 (4,5) 的最优路径如下:

    - (1,1) -> (1,2) ,移动的代价是 |1 - 1| + |2 - 1| = 1 。

    - (1,2) -> (3,3) ,移动使用第一条特殊路径,代价是 2 。

    - (3,3) -> (3,4) ,移动的代价是 |3 - 3| + |4 - 3| = 1.

    - (3,4) -> (4,5) ,移动使用第二条特殊路径,代价是 1 。

总代价是 1 + 2 + 1 + 1 = 5 。

可以证明无法以小于 5 的代价完成从 (1,1) 到 (4,5) 。

示例 2:

输入:start = [3,2], target = [5,7], specialRoads = [[3,2,3,4,4],[3,3,5,5,5],[3,4,5,6,6]]

输出:7

解释:最优路径是不使用任何特殊路径,直接以 |5 - 3| + |7 - 2| = 7 的代价从初始位置到达目标位置。

提示

  • start.length == target.length     == 2

  • 1 <= startX     <= targetX <= 10^5

  • 1 <= startY     <= targetY <= 10^5

  • 1 <= specialRoads.length     <= 200

  • specialRoads[i].length == 5

  • startX <= x1i, x2i <=     targetX

  • startY <= y1i, y2i <=     targetY

  • 1 <= costi     <= 10^5

分析


    首先本题的题意还是有点不清晰,特殊路径有向路径,这一点题目和样例都没有强调。

    称特殊路径的起点和终点为特殊点。从start target 的路径肯定是: start 出发,经过若干个(可能为零个)特殊点,然后再走到 target因此答案其实就是 starttarget 和特殊点构成的有向图上,从 start target 的最短路。我们只要根据题意构造出有向图,然后用 dijkstra 计算最短路即可。

    设特殊路径有 m 条,则特殊点共有 2m 个。由于任意两点均可以到达,因此这张图是完全图,边数为O(m^2)。因此总体复杂度为 O(m^2 logm)

代码

class Solution {public:    int minimumCost(vector<int>& start, vector<int>& target, vector<vector<int>>& specialRoads) {        typedef pair<int, int> pii;        // mp 里存着某个坐标在有向图里的编号        map<pii, int> mp;        // 往图里添加一个坐标为 (x, y) 的点        auto add = [&](int x, int y) {            pii p = pii(x, y);            if (mp.count(p)) return;    // 重复点不存入            int idx = mp.size();        // 点的编号            mp[p] = idx;        };                // 把起点和终点添加到图里        add(start[0], start[1]);        add(target[0], target[1]);        // 把特殊路径的端点添加到图里        for (auto &road : specialRoads) add(road[0], road[1]), add(road[2], road[3]);        int n = mp.size();        // 记录一下每个点的横坐标和纵坐标,方便建图        int X[n], Y[n];        for (auto it = mp.begin(); it != mp.end(); it++) {            X[it->second] = it->first.first;            Y[it->second] = it->first.second;        }        // 开始构建有向图        vector<int> e[n];       // 索引&值 组成记录边的数组        vector<long long> v[n]; // 边的权值        // 首先,任意两点之间都可以互相直接到达        for (int i = 0; i < n; i++)     // 起点            for (int j = 0; j < n; j++) // 终点                if (i != j)                 {                    e[i].push_back(j);  // 记录边                    v[i].push_back(abs(X[i] - X[j]) + abs(Y[i] - Y[j])); // 权值                }           // 其次,图里还存在特殊路径        for (auto &road : specialRoads) {            int sn = mp[pii(road[0], road[1])]; // 起点标号            int fn = mp[pii(road[2], road[3])]; // 终点标号            e[sn].push_back(fn);            v[sn].push_back(road[4]);           // 权值        }                // dijkstra 求从 S 到 T 的最短路        int S = mp[pii(start[0], start[1])], T = mp[pii(target[0], target[1])];        long long dis[n];        memset(dis, -1, sizeof(dis));        typedef pair<long long, int> pli;        priority_queue<pli> pq;        pq.push(pli(0, S));        while (!pq.empty()) {            pli p = pq.top(); pq.pop();            int sn = p.second;            long long d = -p.first;            if(sn==T) return d;            if (dis[sn] >= 0) continue;            dis[sn] = d;            for (int i = 0; i < e[sn].size(); i++) {                int fn = e[sn][i];                if (dis[fn] >= 0) continue;                pq.push(pli(-d - v[sn][i], fn));            }        }        return dis[T];    }};

题目链接

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

参考链接

https://leetcode.cn/problems/minimum-cost-of-a-path-with-special-roads/solution/jian-tu-zui-duan-lu-by-tsreaper-r094/

控制工程研习
好好学习,天天向上
 最新文章