5286. 网格中的最短路径--Leecode刷题

周赛的时候的题目:每次周赛基本上第四道题都做不出来,除了感慨自己菜以外,还会感叹那些做的很快的大佬,是真的很厉害了!!!

题目描述:

给你一个 m * n 的网格,其中每个单元格不是 0(空)就是 1(障碍物)。每一步,您都可以在空白单元格中上、下、左、右移动。

如果您 最多 可以消除 k 个障碍物,请找出从左上角 (0, 0) 到右下角 (m-1, n-1) 的最短路径,并返回通过该路径所需的步数。如果找不到这样的路径,则返回 -1。

示例 1:

输入:
grid =
[[0,0,0],
[1,1,0],
[0,0,0],
[0,1,1],
[0,0,0]],
k = 1
输出:6
解释:
不消除任何障碍的最短路径是 10。
消除位置 (3,2) 处的障碍后,最短路径是 6 。该路径是 (0,0) -> (0,1) -> (0,2) -> (1,2) -> (2,2) -> (3,2) -> (4,2).

示例 2:

输入:
grid =
[[0,1,1],
[1,1,1],
[1,0,0]],
k = 1
输出:-1
解释:
我们至少需要消除两个障碍才能找到这样的路径。

分析:

首先这题我开始的思路是这样,记录每个位置不消除障碍物的最短路径,消除一个障碍物的最短路径,消除两个障碍物的最短路径…消除k个障碍物的最短路径,所以需要构造 dp[row] [col] [k] 来记录,看这个结构就知道,这是一个动态规划的问题,但是问题是,怎么访问各个点的最短路径,从上到下?从左到右?我很蒙。

方法:动态规划+DBS

用一个队列(为啥不用栈,到最后说明),首先放入的是dp[0][0][0]的值为0,之后更新上下左右dp[gx][gy][k],但是注意!!!
首先,只有当dp[gx][gy][k]为-1的时候才需要更新,因为如果已经有值一定是之前更新了的,那么之前更新的步数应该是比当前更新的步数要小的。
第二个问题,当更新的值位置的值
当前位置为grid[gx][gy] == 0时,那么k = a.k(就是从队列出来的k值)
当前位置为grid[gx][gy] == 1时,那么k= a.k+1,因为你当前为1要想到达当前位置,必须消除当前的障碍!!!
之后入队。
这里说明一个问题:这里存在着一个循环,就是你更新下面一个结点(这个结点grid[i][j] = 1)之后,入队,取出,你又更新上面的值,看起来好像是循环了,但是用一个条件,就是你的k是有限的!!!这样只会更新到k,超过k就不做更新,就不会入队循环了!!!

代码如下:

struct node{
    int x,y,k;
    node() {}
    node(int _x,int _y,int _k) { x=_x; y=_y; k=_k; }
};
class Solution {
public:

    int shortestPath(vector<vector<int>>& grid, int k) {

        queue<node> q;
            int row=grid.size();
            int col=grid[0].size();
            int x[4] = {0,0,1,-1};
            int y[4] = {1,-1,0,0};

            int dp[row][col][k+1];
            memset(dp, -1, sizeof(dp));
        dp[0][0][0] = 0;
            q.push(node(0,0,0));

            while(!q.empty()){
                node a = q.front();
                q.pop();

                for(int i = 0;i < 4;i++){
                    int gx = a.x+x[i];
                    int gy = a.y+y[i];
                    if(gx >= 0&&gx < row&&gy >= 0&&gy < col&&a.k+grid[gx][gy] <= k){
                        if(dp[gx][gy][a.k+grid[gx][gy]] == -1){
                            dp[gx][gy][a.k+grid[gx][gy]] = dp[a.x][a.y][a.k]+1;
                            q.push(node(gx,gy,a.k+grid[gx][gy]));
                        }
                    }
                }
            }

            int ans = dp[row-1][col-1][0];
            for(int i = 1;i <= k;i++){
                ans = min(ans,dp[row-1][col-1][i]);
            }
            return ans;
    }
};


这题让我思考了一类题:
1.矩阵
2.每个点具有不同条件下的状态(k不同)
3.且是由上下左右影响,即每个点变化都会影响周围点的变化

解决方法:动态规划+DBS+队列(刚才不懂为啥要用队列现在想想好像是的!!!,因为保证每次更新都是最小值,且下次不用更新了!!!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章