BFS搜索(python)

目录

一、bfs遍历

bfs遍历的步骤

题目链接:最少操作数

题目链接:混镜之地4


一、bfs遍历

        bfs遍历:一般用来求最短路

        给节点分层,从起点,每次把第一步能走到的点全部走一遍。

bfs遍历的步骤

1、将起点入队列,打标记,更行距离。

2、当队列非空。

        2.1、取出对首元素u。

        2.2、当u是终点,break。

        2.3、对于和u相连的所以点v。只要v未标记,将v入队列,打标记,更新距离

来一个模版题:熟悉bfs的应用

题目链接:最少操作数

这道题直接按照bfs的遍历的步骤来模拟即可

from collections import deque


def bfs(s):
    # s:表示对首元素
    # vis:标记数组,与距离数组二和一
    vis = [-1] * 100100

    q = deque()

    # 1、对首元素入队
    q.append(s)
    vis[s] = 0

    # 2、判断队列是否为空
    while len(q) != 0:
        # 2.1、取出对首元素
        u = q.popleft()
        # 2.2、当现在已经到达终点时,直接返回答案
        if u == m:
            return vis[u]
        # 2.3、遍历对于与u相连的v
        for v in [u + 1, u - 1, u * 2]:
            # 特判:看是否越界,是否已经被标记
            if 0 <= v <= 100000 and vis[v] == -1:
                #  更新距离,打标记
                vis[v] = vis[u] + 1
                # 将v打入队列
                q.append(v)


n, m = map(int, input().split())
print(bfs(n))

题目链接:混镜之地4

import sys
from collections import deque


def bfs(x, y, dis):
    # (x, y) 代表起点,dic存储最短距离
    #  初始化队列
    vis = [[0] * m for _ in range(n)]
    q = deque()
    #  把起点放到队列,打标记
    q.append([x, y])
    vis[x][y] = 1
    dis[x][y] = 0
    while len(q) != 0:
        #  在取出元素的时候注意更新
        x, y = q.popleft()
        for x_v, y_v in [(0, 1), (1, 0), (0, -1), (-1, 0)]:
            xx, yy = x + x_v, y + y_v
            #  判断是否越界,是否标记,是否有障碍
            if 0 <= xx < n and 0 <= yy < m and vis[xx][yy] == 0 and li[xx][yy] != '#':
                q.append([xx, yy])
                vis[xx][yy] = 1
                dis[xx][yy] = dis[x][y] + 1


n, m = map(int, input().split())
A, B, C, D = map(int, input().split())
A -= 1
B -= 1
C -= 1
D -= 1
li = [list(input()) for _ in range(n)]
E = int(input())
inf = 10e9
#  dis表示起点到每一个点的最短距离,之所以用inf原因可能永远到达不了终点
dis1 = [[inf] * m for _ in range(n)]
#  dis2a 表示从终点到达每个点的最短距离
dis2 = [[inf] * m for _ in range(n)]
bfs(A, B, dis1)
if dis1[C][D] <= E:
    # 如果到终点的最短路下于等于现有的能量。可以直接打印最短距离
    print(dis1[C][D])
    sys.exit()
bfs(C, D, dis2)
# print(dis1)
# print(dis2)
ans = inf
# 枚举所有的圣泉,找到所需要时间最短的路
for i in range(n):
    for j in range(m):
        if li[i][j] == 'V':
            if dis1[i][j] <= E:
                # dis2[i][j] - E + dis1[i][j] :表示需要再圣泉呆的时间
                # dis1[i][j]:表示到达圣泉所需要的时间
                # dis2[i][j]:表示从圣泉到终点所需要的时间
                ans = min(ans, (dis2[i][j] - E + dis1[i][j]) + dis1[i][j] + dis2[i][j])
if ans != inf:
    print(ans)
else:
    print('No')

题目链接:走迷宫

from collections import deque


def bfs():
    inf = 1e18
    #  vis:表示标记数组
    vis = [[0] * m for _ in range(n)]
    #  il:表示距离数组
    il = [[inf] * m for _ in range(n)]
    # q:表示队列
    q = deque()

    # 起点入队:
    q.append((x1, y1))
    # 打标记:
    vis[x1][y1] = 1
    # 更新距离:
    il[x1][y1] = 0

    while len(q) != 0:
        x, y = q.popleft()
        if x == x2 and y == y2:
            return il[x][y]

        for x_d, y_d in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
            xx = x_d + x
            yy = y_d + y
            if 0 <= xx < n and 0 <= yy < m and Map[xx][yy] == 1 and vis[xx][yy] == 0:
                q.append((xx, yy))
                vis[xx][yy] = 1
                il[xx][yy] = il[x][y] + 1
    return -1


n, m = map(int, input().split())
Map = [list(map(int, input().split())) for _ in range(n)]
x1, y1, x2, y2 = map(int, input().split())
x1 -= 1
y1 -= 1
x2 -= 1
y2 -= 1

print(bfs())

题目链接:马的遍历

        注意:在写代码的时候一定不能太着急,这题的代码一开始把y_d写成了x_d检查了好久好久。

from collections import deque


def bfs():
    #
    il = [[-1] * m for _ in range(n)]
    vis = [[0] * m for _ in range(n)]

    q = deque()

    q.append((x, y))

    il[x][y] = 0
    vis[x][y] = 1
    while len(q) != 0:
        a, b = q.popleft()

        for x_d, y_d in [[-1, 2], [-2, 1], [-2, -1], [-1, -2], [1, 2], [2, 1], [2, -1], [1, -2]]:
            xx = x_d + a
            yy = y_d + b
            if 0 <= xx < n and 0 <= yy < m and vis[xx][yy] == 0:
                q.append((xx, yy))
                vis[xx][yy] = 1
                il[xx][yy] = il[a][b] + 1
    return il


n, m, x, y = map(int, input().split())
x -= 1
y -= 1

for i in bfs():
    for j in i:
        print('{:<5}'.format(j), end='')
    print()


        上面的vis数组也可以直接去掉,用距离数组表示标记数组。代码如下:

from collections import deque


def bfs():
    # 标记数组和距离数组2合1
    il = [[-1] * m for _ in range(n)]

    q = deque()

    q.append((x, y))

    il[x][y] = 0
    while len(q) != 0:
        a, b = q.popleft()

        for x_d, y_d in [[-1, 2], [-2, 1], [-2, -1], [-1, -2], [1, 2], [2, 1], [2, -1], [1, -2]]:
            xx = x_d + a
            yy = y_d + b
            if 0 <= xx < n and 0 <= yy < m and il[xx][yy] == -1:
                q.append((xx, yy))
                il[xx][yy] = il[a][b] + 1
    return il


n, m, x, y = map(int, input().split())
x -= 1
y -= 1

for i in bfs():
    for j in i:
        print('{:<5}'.format(j), end='')
    print()

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值