Python 广度优先搜索(BFS)

广度优先算法

我的理解是在搜索时向一切可能进行的方向搜索,拿经典的走迷宫问题举例子,每次遇到十字路口,就分出三个分身把三个可能的方向都走一遍,这里采用一个数据结构队列,先进先出的保存路径,可以走的状态就保存一下,每次走之前先从队列里面取出来一个状态点,从这一点开始走。

Python实现

Python中已经实现了队列(queue)的结构,直接import就可以使用,然而queue在py2和py3中是有区别的,我在刷oj的时候遇到了这个问题。不过Python给用户提供了比较强大的数据结构列表:list,干脆直接用最基本的list结构来处理这个问题。

使用到的list方法

  1. list.append(obj) 在list尾部添加元素obj
  2. list.pop([index=-1]) 移除并返回列表中的某一项 默认为最后一项 移除第二项可以写作list.pop(1)
  3. del Python的删除关键字,移除第一项可以写作del list[0]

两个实例

最短路径

Pythontip 24一马当先1
下过象棋的人都知道,马只能走’日’字形(包括旋转90°的日),现在想象一
下,给你一个n行m列网格棋盘,
棋盘的左下角有一匹马,请你计算至少需要几步可以将它移动到棋盘的右上
角,若无法走到,则输出-1.
如n=1,m=2,则至少需要1步;若n=1,m=3,则输出-1。

马的路线示意
这个题可以广度搜索,基本思路是每次向八个方向中没走过的方向都走一遍,可以证明重复走过某一点一定会比只经过这一点一次路径要长,建立一个used数组保存使用过的点,不走重复路。建立一个map数组记录距离。题目中没有设置陷阱蹩马腿,还算比较良心。ac代码如下:

# n = 1
# m = 3

map = [[100000000 for x in range(m + 1)] for y in range(n + 1)]
used = [[0 for x in range(m + 1)] for y in range(n + 1)]
map[0][0] = 0
dx = [1, -1, 1, -1, 2, -2, 2, -2]
dy = [2, -2, -2, 2, 1, -1, -1, 1]  # 八个扩展方向
horses = []
horses.append([0, 0])
while (horses):
    h = horses[0]  # 取出第一项
    del horses[0]  # 删除第一项
    if h[0] == n and h[1] == m:  # 已达终点
        break
    for i in range(8):  # 八个方向探索
        nx = h[0] + dx[i]
        ny = h[1] + dy[i]
        if nx >= 0 and nx <= n and ny >= 0 and ny <= m and used[nx][ny] == 0:
            map[nx][ny] = map[h[0]][h[1]] + 1  # 记录长度
            used[nx][ny] = 1  # 已经使用
            horses.append([nx, ny])  # 将该点保存在list中
if map[n][m] != 100000000:
    print(map[n][m])
else:
    print(-1)

最长路径

Pythontip 78 滑雪比赛2
我们把场地分为一个个的格子,给每个格子标定一个整数,代表这个格子所代表的地面的海拔高度。
比赛的参赛者可以从任意一个格子开始,但只能向相邻的四个格子移动,并且目地格子的高度必须
小于现在所在格子的高度。我们假设从一个格子滑行到另一个格子所用的时间为1个单位时间。
现在告诉你滑雪场的大小为n*m, 并给你一个n行m列的整数二维列表H,表示每个格子的海拔高度。
请你计算出在这个场地上最长能滑行多少时间。
如:
n = 4
m = 4
H= [
[1, 2, 3, 4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]
]
则输出 6.

这里显然是从最高点出发,在最低点结束,但是第一个到达最低点的是路径最短的,这里可以换个思路,在list中的点除了x,y坐标外再加上一个新变量t,这个新变量表示了路程或时间,每次都在list中取前端,直到list中没有元素,那么最后一个取出的元素是在list中待的时间最长的,那么它一定表示最长路径。
ac代码如下:

# ~ n = 4
# ~ m = 4
# ~ H= [
    # ~ [1, 2, 3, 4],
    # ~ [5,6,7,8],
    # ~ [9,10,11,12],
    # ~ [13,14,15,16]
    # ~ ]
maxx = 0
maxy = 0
dx = [0, 1, 0, -1]
dy = [1, 0, -1, 0]  # 四个可能的方向
for i in range(n):  # 寻找最高点
    for j in range(m):
        if H[i][j] > H[maxx][maxy]:
            maxx = i
            maxy = j
temp = [maxx, maxy, 0]  # 第一个元素 起点坐标加初始路程
que = []
que.append(temp)
while (que):
    temp = que.pop(0)  # 取第一项
    for i in range(4):  # 四方向搜索
        nx = temp[0] + dx[i]
        ny = temp[1] + dy[i]
        if n > nx >= 0 and m > ny >= 0 and H[nx][ny] < H[temp[0]][temp[1]]:
            t = [nx, ny, temp[2] + 1]  # 新位置的信息
            que.append(t)  # 保存在list中
print(temp[2])  # 输出最后元素的路程

  1. 一马当先 ↩︎

  2. 滑雪比赛 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值