分享

Python|利用BFS求表格中的最短路径

 算法与编程之美 2020-08-08

问题描述

如何用BFS算法解决力扣平台上一道困难题目。给你一个 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
解释:
我们至少需要消除两个障碍才能找到这样的路径。

解决方案

本题我们可以设置起点q为(0,0,k),再规定一个列表d= [[0, 1], [0, -1], [1, 0], [-1, 0]]来控制移动,每经过一次障碍物k就减1,最后在m*n的矩阵里面,终点为(m-1,n-1,0),我们利用BFS广搜找出到达终点的所有结果即可,每次结果经过的点不能重复,我们规定一个集合memory来储存已经经过的点,以确保广搜的时候不会来回重复经过某一个点。

代码示例:

def shortestPath(g,k):
     r, c = len(g), len(g[0])
     d = [[0, 1], [0, -1], [1, 0], [-1, 0]]
     mem = set([(0, 0, k)])
     q = [(0, 0, k)]
     step = 0
     while q:
         n = len(q)
         for _ in range(n):
             x, y, pre = q.pop(0)#将当以前的点赋给(x,y,pre)来进行下一步。
             if x == r - 1 and y == c - 1:
                 return step
             for i, j in d:#利用BFS找出每次移动后的所有点g[nx][ny]
                 nx, ny = x + i, y + j
                 if nx >= 0 and nx  < r and ny >= 0 and ny < c:

#规定条件确保所搜点再矩阵内部
                     if g[nx][ny] == 1:#当遇到障碍物时
                         if pre and (nx,  ny, pre - 1) not in mem:
                              q.append((nx, ny, pre - 1))
                             mem.add((nx, ny, pre - 1))
                     else:
                         if (nx, ny,  pre) not in mem:
                              q.append((nx, ny, pre))
                              mem.add((nx, ny, pre))
         step += 1
     return -1

结语

本题主要考察BFS算法的运用,以及如何用代码在矩阵里进行一些移动,修改变量的操作,这是笔者第一次解决力扣平台上难度为困难的题目,用了将近一下午的时间,为了能更多解决这些类似的题,还要多加练习,希望和笔者一起进步。


END

实习编辑   |   王楠岚

责       编   |   刘仕豪

 where2go 团队


微信号:算法与编程之美          

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多