这个 Dijkstra 代码如何 return 最小值(而不是最大值)?

How does this Dijkstra code return minimum value (and not maximum)?

我正在 LeetCode.com 上解决这个问题 Path With Minimum Effort:

You are given heights, a 2D array of size rows x columns, where heights[row][col] represents the height of cell (row, col). Aim is to go from top left to bottom right. You can move up, down, left, or right, and you wish to find a route that requires the minimum effort. A route's effort is the maximum absolute difference in heights between two consecutive cells of the route. Return the minimum effort required to travel from the top-left cell to the bottom-right cell. For e.g., if heights = [[1,2,2],[3,8,2],[5,3,5]], the answer is 2 (in green).

我的密码是:

class Solution {
public:
    vector<pair<int,int>> getNeighbors(vector<vector<int>>& h, int r, int c) {
        vector<pair<int,int>> n;
        if(r+1<h.size()) n.push_back({r+1,c});
        if(c+1<h[0].size()) n.push_back({r,c+1});
        if(r-1>=0) n.push_back({r-1,c});
        if(c-1>=0) n.push_back({r,c-1});
        return n;
    }
    
    int minimumEffortPath(vector<vector<int>>& heights) {
        int rows=heights.size(), cols=heights[0].size();
        
        using arr=array<int, 3>;
        priority_queue<arr, vector<arr>, greater<arr>> pq;
        vector<vector<int>> dist(rows, vector<int>(cols, INT_MAX));
        pq.push({0,0,0});    //r,c,weight
        dist[0][0]=0;
        
        //Dijkstra
        while(pq.size()) {
            auto [r,c,wt]=pq.top();
            pq.pop();
            
            if(wt>dist[r][c]) continue;
            
            vector<pair<int,int>> neighbors=getNeighbors(heights, r, c);
            for(auto n: neighbors) {
                int u=n.first, v=n.second;
                int curr_cost=abs(heights[u][v]-heights[r][c]);
                if(dist[u][v]>max(curr_cost,wt)) {
                    dist[u][v]=max(curr_cost,wt);
                    pq.push({u,v,dist[u][v]});
                }
            }
        }
        
        return dist[rows-1][cols-1];
    }
};

这被接受了,但我有两个问题:

一个。由于我们更新 dist[u][v] 如果它 大于 max(curr_cost,wt),它如何保证最终我们 return 最小值 需要努力吗?也就是说,我们为什么不结束 return 上面红色部分的努力?

b。一些解决方案,例如 this one、短路和当我们第一次到达右下角(即 if(r==rows-1 and c==cols-1) return wt;)时立即 return - 这是如何工作的?以后再访问右下角的节点时,能不能得到更短的dist

问题陈述要求我们找到具有最小“努力”的路径。
“努力”定义为路径上相邻单元格之间的最大高度差

表达式 max(curr_cost, wt) 处理问题陈述的 maximum 部分。从一个单元格移动到另一个单元格时,到新单元格的距离与到旧单元格的距离相同,或者是高度差,以较大者为准。因此 max(difference_in_heights, distance_to_old_cell).

而 Dijkstra 的算法处理了问题陈述的 minimum 部分,我们不是使用与起始节点的距离,而是使用需要的“努力”从起始节点到任何给定节点。 Dijkstra 尝试最小化距离,因此它最小化了工作量。

Dijkstra 有两个密切相关的概念:visitedexplored。当使用任何传入边到达节点时,节点是 visited。当一个节点的出边被用来访问它的邻居时,它就是 explored。 Dijkstra 的关键设计特征是在一个节点被 探索 之后,对该节点的额外 访问 永远不会增加到该节点的距离。这就是优先队列的原因。优先级队列保证被探索的节点具有任何未探索节点的最小距离。

在示例网格中,红色路径将在绿色路径之前被探索,因为红色路径在最后一步之前的努力为 1,而绿色路径的努力为 2。因此红色路径会将距离设置为右下单元格为 3,即 dist[2][2] = 3.

但是当探索绿色路径时,我们到达行=2,列=1 处的 3,我们有

  • 距离[2][2] = 3
  • curr_cost=2
  • 重量=2

所以 dist[2][2] > max(curr_cost, wt),并且 dist[2][2] 减少到 2。

问题的答案:

一个。红色路径 确实 将右下角的单元格暂时设置为 3 的距离。但是红色路径的结果被丢弃,取而代之的是绿色路径的结果。这是Dijkstra算法求最小值的自然结果。

b。当右下角的节点准备好被探索时,即它位于优先队列的头部,那么它就有了最好的距离,所以算法可以在那个点停止.这也是 Dijkstra 算法的自然结果。优先级队列保证在一个节点被探索之后,以后访问该节点不会减少它的距离。