找到竞技场中危险位置的数量 | 豆包MarsCode AI刷题
目前最棘手的模拟题,要用到dfs来做,条件比较多,要细心处理
摘要
在这道题目中,我们需要确定竞技场迷宫中哪些位置是“危险位置”。危险位置的定义为:无论采取何种移动策略,站在这些位置上都无法到达出口。本文将通过深度优先搜索(DFS)算法从出口出发,找出所有可以到达出口的格子,并统计剩余的无法到达的格子数量。
问题描述
竞技场迷宫
迷宫为一个 的二维地图,包含以下几种元素:
.
:普通地板,可以自由移动到上下左右相邻的格子。O
:出口。U
:向上的传送器,踩上去会被传送到上方的格子。D
:向下的传送器,踩上去会被传送到下方的格子。L
:向左的传送器,踩上去会被传送到左方的格子。R
:向右的传送器,踩上去会被传送到右方的格子。
目标
统计迷宫中所有的“危险位置”数量。即无论如何移动,无法到达出口的位置。
算法原理
为了计算结果,我们采用如下步骤:
- 找到出口:首先遍历地图,确定出口所在的坐标。
- 深度优先搜索 (DFS):
- 从出口出发,探索所有可以到达的格子。
- 如果当前位置是普通地板或传送器,则标记其为“可到达”,并继续探索相邻或传送方向的格子。
- 统计结果:
- 对于每个格子,检查是否被标记为“可到达”。如果不是,则计入危险位置。
解题步骤
数据结构
visited
:记录每个位置是否已访问,防止重复计算。canWalk
:记录从出口可以到达的所有位置。
传送器处理
对于传送器,根据传送规则直接跳转到对应的格子进行递归。
实现代码
Go 实现
package main
import "fmt"
// visited 数组,用于记录每个位置是否已被访问
var visited [][]bool
// solution 函数:计算无法到达出口的位置数量
func solution(N, M int, data [][]rune) int {
exitX, exitY := 0, 0
foundExit := false
// 找到迷宫出口
for i := 0; i < N; i++ {
for j := 0; j < M; j++ {
if data[i][j] == 'O' {
exitX = i
exitY = j
foundExit = true
break
}
}
if foundExit {
break
}
}
// 初始化 visited 数组和 canWalk 数组
visited = make([][]bool, N)
canWalk := make([][]bool, N)
for i := 0; i < N; i++ {
visited[i] = make([]bool, M)
canWalk[i] = make([]bool, M)
}
canWalk[exitX][exitY] = true // 标记出口为可达
dfs(N, M, data, exitX, exitY, canWalk)
// 统计无法到达出口的位置数量
unreachableCount := 0
for i := 0; i < N; i++ {
for j := 0; j < M; j++ {
if !canWalk[i][j] {
unreachableCount++
}
}
}
return unreachableCount
}
// dfs 函数:深度优先搜索,标记所有可到达出口的位置
func dfs(N, M int, data [][]rune, x, y int, canWalk [][]bool) {
// 判断是否越界或已经访问过
if x < 0 || x >= N || y < 0 || y >= M {
return
}
if visited[x][y] {
return
}
// 标记当前位置为已访问
visited[x][y] = true
// 标记当前位置为可到达
canWalk[x][y] = true
// 向上检查
if x-1 >= 0 && (data[x-1][y] == 'D' || data[x-1][y] == '.') {
dfs(N, M, data, x-1, y, canWalk)
}
// 向下检查
if x+1 < N && (data[x+1][y] == 'U' || data[x+1][y] == '.') {
dfs(N, M, data, x+1, y, canWalk)
}
// 向左检查
if y-1 >= 0 && (data[x][y-1] == 'R' || data[x][y-1] == '.') {
dfs(N, M, data, x, y-1, canWalk)
}
// 向右检查
if y+1 < M && (data[x][y+1] == 'L' || data[x][y+1] == '.') {
dfs(N, M, data, x, y+1, canWalk)
}
}
func main() {
pattern := [][]rune{
{'.', '.', '.', '.', '.'},
{'.', 'R', 'R', 'D', '.'},
{'.', 'U', '.', 'D', 'R'},
{'.', 'U', 'L', 'L', '.'},
{'.', '.', '.', '.', 'O'},
}
// 输出结果是否为 10
fmt.Println(solution(5, 5, pattern) == 10)
}
Python 实现
def solution(N, M, data):
"""
计算无法到达出口的位置数量。
"""
# 找到迷宫出口
exit_x, exit_y = 0, 0
for i in range(N):
for j in range(M):
if data[i][j] == 'O':
exit_x, exit_y = i, j
break
# 初始化 visited 和 can_walk 数组
visited = [[False for _ in range(M)] for _ in range(N)]
can_walk = [[False for _ in range(M)] for _ in range(N)]
# 出口是可到达的
can_walk[exit_x][exit_y] = True
# 深度优先搜索
def dfs(x, y):
# 判断是否越界或已访问
if x < 0 or x >= N or y < 0 or y >= M or visited[x][y]:
return
# 标记当前位置
visited[x][y] = True
can_walk[x][y] = True
# 上
if x - 1 >= 0 and (data[x - 1][y] == 'D' or data[x - 1][y] == '.'):
dfs(x - 1, y)
# 下
if x + 1 < N and (data[x + 1][y] == 'U' or data[x + 1][y] == '.'):
dfs(x + 1, y)
# 左
if y - 1 >= 0 and (data[x][y - 1] == 'R' or data[x][y - 1] == '.'):
dfs(x, y - 1)
# 右
if y + 1 < M and (data[x][y + 1] == 'L' or data[x][y + 1] == '.'):
dfs(x, y + 1)
# 开始从出口位置进行搜索
dfs(exit_x, exit_y)
# 统计无法到达出口的位置数量
unreachable_count = 0
for i in range(N):
for j in range(M):
if not can_walk[i][j]:
unreachable_count += 1
return unreachable_count
if __name__ == "__main__":
pattern = [
['.', '.', '.', '.', '.'],
['.', 'R', 'R', 'D', '.'],
['.', 'U', '.', 'D', 'R'],
['.', 'U', 'L', 'L', '.'],
['.', '.', '.', '.', 'O']
]
# 输出结果是否为 10
print(solution(5, 5, pattern) == 10)