简单搜索——偶遇的一道迷宫问题题目

简单搜索

题目

一个 H 行 M 列的迷宫 S,迷宫中 ‘#’ 代表墙壁, ‘.’ 代表可走位置。
每一步移动在一个可走放歌里,可以水平或者垂直移动到相邻的一个可走放个中。墙壁方格不能走,也不能对角线移动。
你可以选择任意一个起点方格和终点方格(这两个方格必须为可走方格,且可以相互到达)。从选择的七点方格用最小的步数移动到终点方格。
本题需要你最优的选择起点方格和终点方格,使你的最小移动步数尽可能大,你需要计算这个步数的最大值。

输入

第一行为两个整数 H,M(1<=H,M<=60)
接下来 H 行,每行 M 个字符,代表迷宫 S
S 中至少包含 2 个字符 ‘.’

输出

一行一个整数代表答案——最小移动步数的最大值

示例

  • 输入
    3 3

    .#.
  • 输出
    4
  • 输入
    5 5
    …#.
    …#.
    .#…
    #…
    .#…#
  • 输出
    8
  • 输入
    5 5
    #…#.
    …#.

    #.#…
    …#
  • 输出
    8

思路

该题和简单搜索——Dungeon Master很像,只不过在最短路径(最短时间)上面套一个起始点、终止点的选择情况。
该题其实还有时间、内存限制,但是我没法去测试,对于题目给出的示例输入输出倒是测试出来都对的,如果有不对的地方还请大佬指点。
此外,本来算法我都是 C++ 写的,这一次也是应题目要求要用python 写,但是思路我觉得都是一样的。

代码

import copy


# 定义一个用于表示在迷宫中移动时的点的信息,
# 包括 该点的位置:(x, y) 和移动到该点时已经移动了多少步:step
class coordinate:
    def __init__(self, x, y, step):
        self.x = x
        self.y = y
        self.step = step


def bfs(h, m, start_x, start_y, stop_x, stop_y, maze):
    # 定义对于迷宫中每一个位置有可能走的方向:
    # 上一行、下一行  前一列、后一列
    next_step = [[-1, 0], [1, 0], [0, -1], [0, 1]]
    # 列表模拟队列
    q = []
    # 定义起始点
    current = coordinate(start_x, start_y, 0)
    # 将起始点加到队列中
    q.append(current)
    # 当队列不为空时
    while len(q) != 0:
        # 取队列首元素
        x = q[0].x
        y = q[0].y
        step = q[0].step
        # 将此处位置改变为 '#'
        maze[x][y] = '#'
        # 遍历每一个可行方向
        for s in range(4):
            # 如果迷宫尺寸
            if (((x + next_step[s][0]) >= 0) and ((x + next_step[s][0]) < h) and ((y + next_step[s][1]) >= 0) and ((y + next_step[s][1]) < m)):
                # 定义将该方向移动一步后的点
                next = coordinate(x + next_step[s][0], y + next_step[s][1], step + 1)

                # 如果该方向移动一步后的点为终止点,则直接返回此时步数
                if (next.x == stop_x) and (next.y == stop_y):
                    return next.step

                # 如果该方向移动一步后的点为可行点
                # 则将该点加到队列中,并将迷宫的该点位置改变为 '#'
                if (maze[next.x][next.y] == '.'):
                    q.append(next)
                    maze[next.x][next.y] = '#'

        # 队列首元素四个方向遍历完后,将首元素删除
        del q[0]
    return 0


# 输入行h、列m
input_str = input()
h = int(input_str.split(" ")[0])
m = int(input_str.split(" ")[1])

# 输入迷宫
maze = []
for i in range(h):
    maze_row = list(input())
    maze.append(maze_row)

# 定义 x_list、y_list
# 用于保存迷宫中可行点的横坐标、纵坐标
x_list = []
y_list = []
for i in range(h):
    for j in range(m):
        if (maze[i][j] == '.'):
            x_list.append(i)
            y_list.append(j)

# 定义 all_coor
# 换一种形式保存迷宫中可行点
# example: [[1,2], [3,4]]
all_coor = []
for i in range(len(x_list)):
    coor = []
    coor.append(x_list[i])
    coor.append(y_list[i])
    all_coor.append(coor)

longest_step_number = 0

# 遍历每一个可行点
for i in range(len(all_coor)):
    # 取一个可行点作为起始点
    coor_start = all_coor[i]
    # 除了起始点外其他点保存到 all_coor_1
    # 用于存储终止点
    all_coor_1 = list(filter(lambda x: x != coor_start, all_coor))

    # 遍历每一个终止点
    for j in range(len(all_coor_1)):
        coor_stop = all_coor_1[j]
        # maze_new 存在的意义在于 bfs 中会改变迷宫内部内容,为了下一个循环时还能读取原始迷宫内容
        # 所以传入 bfs 函数的迷宫是 maze 的 deepcopy
        maze_new = []
        maze_new = copy.deepcopy(maze)
        # 调用 bfs 函数,得到这一种(起始点,终止点)情况下的最小步数
        step_number = bfs(h, m, coor_start[0], coor_start[1], coor_stop[0], coor_stop[1], maze_new)
        if step_number > longest_step_number:
            longest_step_number = step_number

print(longest_step_number)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值