1. 题目

给你一个 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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-in-a-grid-with-obstacles-elimination
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题

  • dp[i][j][s] 表示到(i,j)位置,消除了s个障碍物的最短步数
  • 先用 BFS搜索跟起点相连的 非障碍物(0),记录每个到达的 0 位置 dp[i][j][0]的步数(BFS的层数)
  • 然后在遍历所有可能的s,遍历所有的位置 i,j,下一个位置状态 ni,nj
  • 如果(grid[ni][nj] && s+1 <= k) 是障碍物, 且还可以搬走
    dp[ni][nj][s+1] = min(dp[ni][nj][s+1], dp[i][j][s]+1)
  • 如果 grid[ni][nj]不是障碍物
    dp[ni][nj][s] = min(dp[ni][nj][s], dp[i][j][s]+1)
class Solution {public:int shortestPath(vector<vector<int>>& grid, int k) {vector<vector<int>> dir = {{1,0},{0,1},{0,-1},{-1,0}};int m = grid.size(), n = grid[0].size(), i, j, ni, nj, s = 0, d;vector<vector<vector<int>>> dp(m,vector<vector<int>>(n, vector<int>(k+1, INT_MAX)));// dp[i][j][s] 表示到(i,j)位置,消除了s个障碍物的最短步数dp[0][0][0] = 0;vector<vector<bool>> vis(m, vector<bool>(n,false));queue<vector<int>> q;q.push({0,0});vis[0][0] = true;while (!q.empty()) //广度优先查找所有0位置,不用搬走障碍{int size = q.size();while(size--){i = q.front()[0];j = q.front()[1];q.pop();dp[i][j][0] = s;//不用搬走障碍的最短步数for(d = 0; d < 4; ++d){ni = i+dir[d][0];nj = j+dir[d][1];if(ni<0 || ni >= m || nj<0 || nj >= n || vis[ni][nj] || grid[ni][nj])continue;//出界了,访问过,是障碍物q.push({ni,nj});vis[ni][nj] = true;}}s++;}for(s = 0; s <= k; s++){   //障碍物for(i = 0; i < m; i++) { //位置 ifor(j = 0; j < n; j++){ //位置 jif(dp[i][j][s] == INT_MAX)continue;//状态不能走到,下一个for(d= 0; d < 4; ++d){  //向4个方向移动,下一个坐标ni = i+dir[d][0];nj = j+dir[d][1];if(ni<0 || ni >= m || nj<0 || nj >= n)continue;//出界了,下一个if(grid[ni][nj] && s+1 <= k)//下一个位置为障碍物, 还可以搬走dp[ni][nj][s+1] = min(dp[ni][nj][s+1], dp[i][j][s]+1);else if(!grid[ni][nj])//不是障碍物dp[ni][nj][s] = min(dp[ni][nj][s], dp[i][j][s]+1);}}}}int minstep = INT_MAX;for(s = 0; s <= k; ++s)minstep = min(minstep, dp[m-1][n-1][s]);return minstep==INT_MAX ? -1 : minstep;}
};

640 ms 25.2 MB

  • 或者直接BFS,队列内存储<i, j, 搬运障碍物次数>
class Solution {public:int shortestPath(vector<vector<int>>& grid, int k) {vector<vector<int>> dir = {{1,0},{0,1},{0,-1},{-1,0}};int m = grid.size(), n = grid[0].size(), i, j, ni, nj, step = 0, curs, d;vector<vector<vector<bool>>> vis(m,vector<vector<bool>>(n, vector<bool>(k+1, false)));queue<vector<int>> q;q.push({0,0,0});// i, j, s障碍物搬了几次vis[0][0][0] = true;while (!q.empty()) {int size = q.size();while(size--){i = q.front()[0];j = q.front()[1];curs = q.front()[2];if(i==m-1 && j==n-1)return step;q.pop();for(d = 0; d < 4; ++d){ni = i+dir[d][0];nj = j+dir[d][1];if(ni<0 || ni >= m || nj<0 || nj >= n)continue;//出界了if(grid[ni][nj] && curs+1 <= k && !vis[ni][nj][curs+1])//是障碍物, 还能搬走{vis[ni][nj][curs+1] = true;q.push({ni,nj,curs+1});}else if(!grid[ni][nj] && !vis[ni][nj][curs])//不是障碍物{vis[ni][nj][curs] = true;q.push({ni,nj,curs});}}}step++;}return -1;}
};

400 ms 41.1 MB

python3 解答

class Solution:def shortestPath(self, grid: List[List[int]], k: int) -> int:import queuedir = [[1,0],[0,1],[0,-1],[-1,0]]m, n = len(grid), len(grid[0])step = 0vis = [[[False]*(k+1) for _ in range(n)] for _ in range(m)]q = queue.Queue(m*n*(k+1))q.put([0,0,0])vis[0][0][0] = Truewhile not q.empty():size = q.qsize()while size > 0:qt = q.get()i = qt[0]j = qt[1]curs = qt[2]if i==m-1 and j==n-1:return stepfor d in range(4):ni = i+dir[d][0]nj = j+dir[d][1]if ni<0 or ni>=m or nj<0 or nj>=n:continueif grid[ni][nj] and curs+1 <= k and not vis[ni][nj][curs+1]:vis[ni][nj][curs+1] = Trueq.put([ni,nj,curs+1])elif not grid[ni][nj] and not vis[ni][nj][curs]:vis[ni][nj][curs] = Trueq.put([ni,nj,curs])size -= 1step += 1return -1

2200 ms 18.5 MB

LeetCode 1293. 网格中的最短路径(DP/BFS)相关推荐

  1. leetcode 1293. Shortest Path in a Grid with Obstacles Elimination | 1293. 网格中的最短路径(BFS)

    题目 https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/ 题解 DFS 递归超时,看了评 ...

  2. [leetcode]1293. 网格中的最短路径

    struct Node {int x, y;int rest; //还可以消几个障碍物int dist; //距离Node(int _x,int _y, int _rest, int _dist):x ...

  3. LeetCode 1091. 二进制矩阵中的最短路径(BFS)

    1. 题目 在一个 N × N 的方形网格中,每个单元格有两种状态:空(0)或者阻塞(1). 一条从左上角到右下角.长度为 k 的畅通路径, 由满足下述条件的单元格 C_1, C_2, ..., C_ ...

  4. LeetCode 1091 二进制矩阵中的最短路径问题[BFS 队列] HERODING的LeetCode之路

    解题思路: 使用广度优先遍历的方法,可以遍历下一步能走的位置,一般用到广度优先就离不开队列,队列存储着当前轮次能够走的位置,每一轮都要将能走的长度++,如果队列无元素,说明无处可走,此时没有到终点就直 ...

  5. LeetCode 1129. 颜色交替的最短路径(BFS)

    文章目录 1. 题目 2. 解题 1. 题目 在一个有向图中,节点分别标记为 0, 1, ..., n-1. 这个图中的每条边不是红色就是蓝色,且存在自环或平行边. red_edges 中的每一个 [ ...

  6. LeetCode 1730. 获取食物的最短路径(BFS)

    文章目录 1. 题目 2. 解题 1. 题目 你现在很饿,想要尽快找东西吃.你需要找到最短的路径到达一个食物所在的格子. 给定一个 m x n 的字符矩阵 grid ,包含下列不同类型的格子: '*' ...

  7. LeetCode 1765. 地图中的最高点(BFS)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个大小为 m x n 的整数矩阵 isWater ,它代表了一个由 陆地 和 水域 单元格组成的地图. 如果 isWater[i][j] == 0 ...

  8. leetcode1091. 二进制矩阵中的最短路径(bfs)

    在一个 N × N 的方形网格中,每个单元格有两种状态:空(0)或者阻塞(1).一条从左上角到右下角.长度为 k 的畅通路径,由满足下述条件的单元格 C_1, C_2, ..., C_k 组成:相邻单 ...

  9. LeetCode 1391. 检查网格中是否存在有效路径(BFS)

    文章目录 1. 题目 2. 解题 2.1 BFS 2.2 爆栈的DFS 2.3 不爆栈的DFS 1. 题目 给你一个 m x n 的网格 grid.网格里的每个单元都代表一条街道.grid[i][j] ...

最新文章

  1. spring-boot的access日志格式修改
  2. 《LeetCode力扣练习》第6题 C语言版 (做出来就行,别问我效率。。。。)
  3. 使用VC++2015 实现XP按钮效果
  4. java LinkedLis t的26种使用方法
  5. mysql版本不同会导致语法错误码_神奇的 SQL,Group By 真扎心,原来是这样!
  6. js 页面载入时的执行顺序
  7. python 把多个list合并为一个并去重内容_110道Python面试题(上)
  8. linux用户管理和文件权限
  9. 设计每个网站时所追求的5个目标
  10. vue router 懒加载实现
  11. JS去除数组中重复的值(四种方法)
  12. 深入理解C语言内存管理
  13. Canvas 画时钟
  14. php laravel手册,学习Laravel
  15. JavaWeb开发——注册登录的表单验证
  16. 【手撕算法】PatchMatch图像修复算法C++实现
  17. Android 指定宽高的ViewGroup
  18. 服务器cpu e系列和x系列,英特尔至强cpu,x系列和e系列哪个更好?
  19. 射频遥控:固定码与学习码的区别
  20. 解决rk3288 摄像头顿卡问题解决过程

热门文章

  1. 解决python中html 代码被注释掉 依旧被解释导致报错ERROR:tornado.access:500 GET /home (xxx.xxx.xxx.xxx)
  2. 关于eclipse项目红色感叹号的解决办法
  3. LeetCode2——Add Two Numbers(两个链表中的数字相加,形成新链表)
  4. c++远征之多态篇——纯虚函数和抽象类、接口类
  5. 二维数组数和指针操作的理解
  6. Install Python3.6 on Amazon Linux/EC2 在Amazon Linux实例中安装使用Python3.6
  7. 使用spring的@autowired注解,无法实例化dao
  8. 图的定义与术语 - 数据结构和算法54
  9. 《塔木德智慧全书》(之四)
  10. WCF分布式开发步步为赢系列