📜  门|门CS 2008 |第 76 题(1)

📅  最后修改于: 2023-12-03 14:58:36.806000             🧑  作者: Mango

题目介绍

题目名称:门|门CS 2008

题目链接:AcWing 76. 门|门CS 2008

本题是一个经典的搜索问题,需要使用BFS或DFS算法实现,涉及迷宫地图的处理。

题目描述

给定一个n行m列的迷宫地图(其中S表示起点,T表示终点,#表示障碍物,.表示通路),请编写一个算法,计算从起点S到终点T的最短路径长度。

输入格式

第一行包含两个整数n和m。

接下来n行,每行包含m个字符。

输出格式

输出一个整数,表示从起点S到终点T的最短路径长度。

输入样例
5 5
S#...
...#.
...#.
.#.#.
...T.
输出样例
9
解题思路

本题需要使用BFS或DFS算法来搜索迷宫的最短路径。

使用BFS算法时,我们可以通过队列来实现搜索。

具体步骤如下:

  1. 将起点S加入队列,并将起点S的路径长度设置为0。
  2. 循环扩展队首元素,对队首元素的上、下、左、右四个方向进行扩展,并将新的元素加入队列中。
  3. 如果队首元素已经是终点T,则返回其路径长度。
  4. 如果队列为空且仍未找到终点,则返回-1。

使用DFS算法时,我们可以通过递归函数来实现搜索。

具体步骤如下:

  1. 将起点S的路径长度初始化为0,调用递归函数dfs(S,0)。
  2. 在dfs函数中,对当前点的上、下、左、右四个方向进行搜索,并将其路径长度加1。
  3. 如果当前点已经是终点T,则将其路径长度与当前最小路径长度进行比较,并更新最小路径长度。
  4. 对于每一个搜索到的新点,如果其路径长度小于最小路径长度,才继续进行搜索,否则直接返回。
代码演示
BFS实现
# 标准BFS算法求解最短路径
n, m = map(int, input().split())
maze = [input() for _ in range(n)]

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

# 计算起点和终点的坐标
for i in range(n):
    for j in range(m):
        if maze[i][j] == 'S':
            start_x, start_y = i, j
        elif maze[i][j] == 'T':
            end_x, end_y = i, j

queue = [(start_x, start_y, 0)]
visited = {(start_x, start_y)}

while queue:
    x, y, step = queue.pop(0)
    if x == end_x and y == end_y:
        print(step)
        break
    for i in range(4):
        next_x, next_y = x + dx[i], y + dy[i]
        if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
            continue
        if maze[next_x][next_y] == '#' or (next_x, next_y) in visited:
            continue
        queue.append((next_x, next_y, step + 1))
        visited.add((next_x, next_y))
else:
    print(-1)
DFS实现
# 标准DFS算法求解最短路径
n, m = map(int, input().split())
maze = [input() for _ in range(n)]

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

# 计算起点和终点的坐标
for i in range(n):
    for j in range(m):
        if maze[i][j] == 'S':
            start_x, start_y = i, j
        elif maze[i][j] == 'T':
            end_x, end_y = i, j

# 初始化最小路径长度
min_step = float('inf')

def dfs(x, y, step):
    global min_step
    # 如果已经找到终点,则更新最小路径长度
    if x == end_x and y == end_y:
        min_step = min(min_step, step)
        return
    # 对四个方向进行搜索
    for i in range(4):
        next_x, next_y = x + dx[i], y + dy[i]
        # 判断是否越界或者遇到障碍物
        if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m or maze[next_x][next_y] == '#':
            continue
        # 只搜索路径长度小于最小路径长度的点
        if step + 1 < min_step:
            # 将已访问的点标记为已访问
            maze[next_x] = maze[next_x][:next_y] + '#' + maze[next_x][next_y+1:]
            dfs(next_x, next_y, step+1)
            # 回溯,将已访问标记的点还原
            maze[next_x] = maze[next_x][:next_y] + '.' + maze[next_x][next_y+1:]

dfs(start_x, start_y, 0)

if min_step < float('inf'):
    print(min_step)
else:
    print(-1)
代码说明
  1. 搜索时需要判断是否越界或遇到障碍物,以及是否已经访问过。
  2. BFS算法中,可以使用visited集合来记录已经访问过的节点。DFS算法中,可以使用maze矩阵来记录已经访问过的节点。
  3. DFS算法中,需要注意回溯时将已访问标记的点还原。