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

📅  最后修改于: 2023-12-03 15:42:22.218000             🧑  作者: Mango

题目介绍

本题为"门"问题,属于图论中的最短路问题。给定一个 $n\times m$ 的迷宫地图,地图中的每个位置可能是墙(用 "#" 表示),也可能是平原(用 "." 表示),还可能是门(用 "S" 和 "E" 表示)。

地图中存在多个门,每个门的编号为 $1$ 至 $9$。其中,门的编号一定是成对出现的,即如果存在 $i$ 号门,则一定存在 $i+9$ 号门。对于每一对相同编号的门,它们之间会存在一些单向门,即只能从一个门进入,而无法从另一个门出去。两个门之间如果有多个单向门,我们认为它们是相互可达的。

现在要求你从某一个门出发,依次经过一些单向门,到达另一个门(编号与起点不同),问最少需要经过多少个单向门。

程序实现

本题的解法是使用 BFS 算法,每次将当前节点的所有可到达节点加入队列中。

我们需要记录每个门对应的编号和出发门的编号。

对于每个位置,可能有三种情况:可达、不可达或者是另一个门,我们用三个数组 $able$、$unable$ 和 $door$ 分别保存这三种情况。

由于每个节点只会被遍历一次,所以时间复杂度为 $O(nm)$,空间复杂度为 $O(nm)$。

以下是 python 代码实现:

# -*- coding: utf-8 -*-
from collections import deque

# 输入地图信息
n, m = map(int, input().split())
maze = [list(input()) for _ in range(n)]

# 初始化数组
able = [[False] * m for _ in range(n)]  # 可达
unable = [[False] * m for _ in range(n)]  # 不可达
door = [[0] * m for _ in range(n)]  # 门编号
start = None

# 记录每一个门对应的编号
doors = [[] for _ in range(10)]

# 处理地图
for i in range(n):
    for j in range(m):
        if maze[i][j] == "S":
            start = (i, j)  # 记录起始点
        elif maze[i][j] in "123456789":
            door[i][j] = int(maze[i][j])
            doors[int(maze[i][j])].append((i, j))
        elif maze[i][j] == ".":
            able[i][j] = True

# 记录最少需要经过的门数
ans = float("inf")

# BFS 遍历
for s in doors[door[start[0]][start[1]]]:  # 从同一个门编号的门中开始遍历
    visited = [[False] * m for _ in range(n)]
    visited[s[0]][s[1]] = True
    q = deque([(s, 0)])
    while q:
        pos, step = q.popleft()
        if maze[pos[0]][pos[1]] != "E" and door[pos[0]][pos[1]] != 0 and door[pos[0]][pos[1]] != door[start[0]][start[1]]:
            # 如果走到终点且到该终点的门的编号和起始门的编号不一样,则更新最小步数
            ans = min(ans, step)
            break
        for dx, dy in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
            nx, ny = pos[0] + dx, pos[1] + dy
            if 0 <= nx < n and 0 <= ny < m and not visited[nx][ny]:
                if able[nx][ny] or (door[nx][ny] != 0 and door[nx][ny] == door[pos[0]][pos[1]]):
                    visited[nx][ny] = True
                    q.append(((nx, ny), step + 1))
print(ans)

以上就是本题的解题思路和算法实现。