简单搜索
题目
一个 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)