191.(1293)网格中的最短路径

题目描述:

给你一个 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
解释:
我们至少需要消除两个障碍才能找到这样的路径。
提示:

grid.length == m
grid[0].length == n
1 <= m, n <= 40
1 <= k <= m*n
grid[i][j] == 0 or 1
grid[0][0] == grid[m-1][n-1] == 0

思路:

1、广度优先遍历

2、多次走过某一网格的情况该怎么处理。记录每次经过该网格时的K值,如果当前经过时的K值大于上一次经过的K值,则可以走该网格。因为K值越大,从该网格走过时走的越远

代码:

class Solution {
public:
    int shortestPath(vector<vector<int>>& grid, int k) {
        int m=grid.size(),n=grid[0].size();
        if(m==1&&n==1)return 0;
        if(k>=m+n-2)return m+n-2;
        queue<vector<int>>q;
        vector<int>temp(4);
        vector<vector<int>>status(m,vector<int>(n));
        int res=INT_MAX,x,y;
        int disx[4]={1,-1,0,0};
        int disy[4]={0,0,-1,1};
        q.push(vector<int>{0,0,0,k});
        while(!q.empty())
        {
            temp=q.front();
            q.pop();
            temp[2]++;
            for(int i=0;i<4;i++)
            {
                x=temp[0]+disx[i];
                y=temp[1]+disy[i];
                if(x>=m||x<0||y>=n||y<0||grid[x][y]==2)continue;
                if(temp[3]==0&&grid[x][y]==1)continue;
                if(x==m-1&&y==n-1)
                {
                    res=min(res,temp[2]);
                    continue;
                }
                if(temp[3]>status[x][y])
                {
                    if(grid[x][y]==1)q.push(vector<int>{x,y,temp[2],temp[3]-1});
                    else if(grid[x][y]==0) q.push(vector<int>{x,y,temp[2],temp[3]});
                    status[x][y]=temp[3];
                }
            }
        }
        return res==INT_MAX?-1:res;
    }
};

执行效率:

执行用时:16 ms, 在所有 C++ 提交中击败了80.68%的用户

内存消耗:8.7 MB, 在所有 C++ 提交中击败了74.68%的用户

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值