我好想逃却逃不掉
问题描述
曾经的我不过是一介草民,混迹市井,默默无名。直到我被罗马的士兵从家乡捉走丢进竞技场……
对手出现了,我架紧盾牌想要防御,只觉得巨大的冲击力有如一面城墙冲涌而来,击碎了我的盾牌,我两眼发昏,沉重的身躯轰然倒地。
——我好想逃。
但罗马最大的竞技场,哪有这么容易逃得掉。工程师们早就在地上装了传送机关,虽不会伤人,却会将站在上面的人传到它指向的位置。若是几个传送机关围成一个环,不小心踩在上面的人就会被一圈圈地反复传送……想到这里,我不由得打了个寒颤。必须避开这些危险的地方!
你的任务是找出在迷宫的哪些位置,当玩家移动到此处时,无论接下来如何移动都无法再到达出口。
测试样例
样例1:
输入:
N = 5, M = 5, data = [".....", ".RRD.", ".U.DR", ".ULL.", "....O"]
输出:10
样例2:
输入:
N = 4, M = 4, data = [".R.O", "U.L.", ".D..", "..RD"]
输出:2
样例3:
输入:
N = 3, M = 3, data = [".UO", "L.R", "D.."]
输出:8
代码提示
- 优化传送点的处理:
当前代码在处理传送点时,直接递归调用can_reach_exit函数。这可能会导致重复计算和栈溢出。可以考虑使用一个visited数组来记录已经访问过的位置,避免重复访问。 - 反向思考:
你可以从出口开始,反向标记所有可以到达出口的位置。这样,所有未被标记的位置就是无法到达出口的“危险位置”。 - 使用广度优先搜索(BFS) :
从出口开始,使用 BFS 来标记所有可以到达的位置。BFS 更适合处理这种需要遍历所有可能路径的问题。 - 处理边界情况:
确保在处理传送点时,不会传送到迷宫之外的位置。
代码解释
python def solution(N, M, data):
# 构建迷宫矩阵
maze = []
for row in data:
if isinstance
(row, list):
maze.append
(row)
else:
maze.append
(list(row))
-
构建迷宫矩阵:
maze是一个二维列表,用于存储迷宫的地图。data是输入的迷宫数据,可能是一个二维列表或字符串列表。- 通过遍历
data,将每一行转换为列表并添加到maze中。
python
# 方向映射
directions = {
'U': (-1, 0), #
上
'D': (1, 0), #
下
'L': (0, -1), #
左
'R': (0, 1) #
右
}
-
方向映射:
directions是一个字典,用于映射传送点的方向到相应的坐标变化。'U'表示向上移动,坐标变化为(-1, 0)。'D'表示向下移动,坐标变化为(1, 0)。'L'表示向左移动,坐标变化为(0, -1)。'R'表示向右移动,坐标变化为(0, 1)。
python
def is_valid(x, y):
return 0 <= x < N
and 0 <= y < M
-
边界检查:
is_valid函数用于检查坐标(x, y)是否在迷宫的有效范围内。- 如果
x和y都在[0, N)和[0, M)范围内,则返回True,否则返回False。
python
def can_reach_exit
(start_x, start_y,
visited):
# 越界检查
if not is_valid
(start_x, start_y)
:
return False
# 如果已经访问过,说
明形成了环
if (start_x,
start_y) in
visited:
return False
# 到达出口
if maze[start_x]
[start_y] == 'O':
return True
# 记录当前位置为已访
问
visited.add
((start_x,
start_y))
# 如果是传送点
if maze[start_x]
[start_y] in
directions:
dx, dy =
directions
[maze[start_x]
[start_y]]
next_x,
next_y =
start_x + dx,
start_y + dy
return
can_reach_exit
(next_x,
next_y,
visited)
# 如果是普通点,尝试
四个方向
for dx, dy in
directions.values
():
next_x,
next_y =
start_x + dx,
start_y + dy
if is_valid
(next_x,
next_y) and
can_reach_exit
(next_x,
next_y,
visited.copy
()):
return
True
return False
-
可达性检查:
can_reach_exit函数用于检查从(start_x, start_y)是否可以到达出口'O'。- 越界检查:如果当前位置越界,返回
False。 - 环检测:如果当前位置已经访问过,说明形成了环,返回
False。 - 到达出口:如果当前位置是出口
'O',返回True。 - 记录访问:将当前位置标记为已访问。
- 传送点处理:如果当前位置是传送点,计算传送后的位置,并递归检查传送后的位置。
- 普通点处理:如果当前位置是普通点,尝试四个方向,递归检查每个方向的可达性。注意这里每次递归调用时都创建一个新的
visited集合的副本,以避免状态共享问题。
python # 统计无法到达出口的位置数
量
count = 0
for i in range(N):
for j in range(M):
if maze[i][j]
!= 'O': # 不
考虑出口本身
if not
can_reach_
exit(i,
j, set()):
count
+= 1
return count
-
统计无法到达出口的位置数量:
- 遍历迷宫中的每个位置
(i, j)。 - 如果当前位置不是出口
'O',则调用can_reach_exit函数检查是否可以到达出口。 - 如果无法到达出口,则计数器
count加 1。 - 最后返回
count,即无法到达出口的位置数量。
- 遍历迷宫中的每个位置
python
if name == "main":
# Add your test cases
here
pattern = [
[".", ".", ".",
".", "."],
[".", "R", "R",
"D", "."],
[".", "U", ".",
"D", "R"],
[".", "U", "L",
"L", "."],
[".", ".", ".", ".
", "O"]
]
print(solution(5, 5,
pattern) == 10)
-
主函数:
- 定义了一个测试用例
pattern,并调用solution函数进行测试。 - 打印结果,检查是否符合预期(预期结果为 10)。
- 定义了一个测试用例
总结
这段代码的主要功能是统计迷宫中无法到达出口的位置数量。通过递归检查每个位置是否可以到达出口,并使用 visited 集合来避免重复访问和环检测。代码的核心在于 can_reach_exit 函数,它通过递归和状态记录来判断可达性。