题目解析:我好想逃却逃不掉 | 豆包MarsCode AI刷题
问题描述:
给出一个M×N的地图,地图的每个位置有以下可能:
.:表示普通地板,可以自由移动到上下左右相邻的格子(不可以走斜线)O:表示出口U:表示向上的传送器,踩上去会被强制传送到上方的格子D:表示向下的传送器,踩上去会被强制传送到下方的格子L:表示向左的传送器,踩上去会被强制传送到左方的格子R:表示向右的传送器,踩上去会被强制传送到右方的格子
问题是需要找出所有无论如何都不能移动到O的位置个数。
1.思考如何解决
要解决这个问题,我们需要识别出在给定的地图上所有无法到达出口 'O' 的位置。可以通过图搜素算法来解决,在这里考虑到的是采用广度优先搜素算法(BFS)来对地图的每一个点进行遍历。
在这里简单介绍下广度优先搜素算法(BFS)
BFS是一种用于图的遍历或搜索的算法。它从根节点(在这里就是指地图的出口了)开始,逐层遍历地图,直到找到目标节点或遍历完整个图。每次遍历4个方向。
与深度优先搜素算法那样一次遍历一层,遍历到底部为止。不同的是,他是一次遍历一层,遍历4个方向。
对于这个问题,最好是用到广度优先搜素,如果采用深度优先搜素的话,在遇到传送器时可能会不断循环,因为它会沿着路径深入直到无法继续为止。并且由于递归的性质,同一个位置可能会被多次访问
2.具体思路
要解决这个问题,我们可以按照以下步骤进行:
2.1初始化
- 创建一个
visited二维数组,用于记录每个位置能否访问到出口。 - 创建一个
queue,用于存储BFS过程中的节点。
2.2寻找出口
- 遍历地图,找到所有标记为 'O' 的出口位置,并将这些位置加入
queue,同时将它们标记为能访问到出口。
2.3广度优先搜索从出口开始遍历地图(BFS)
- 使用BFS从每个出口开始遍历地图,标记所有可达的位置。
- 定义了一个
directions字典,用于存储四个不同方向的移动。 - 在BFS过程中,对于每个当前位置,检查它的四个方向(上、下、左、右)以及传送器的效果。
- 在确保没超出地图边界的情况下,对队列
queue中每个方向进行遍历。 - 如果遇到传送器,需要特殊处理。
- 如果遇到普通地板,因为我们是从出口开始进行遍历,如果我们遇到普通地板,说明能从这个普通地板直接访问到出口。则将其加入
queue并标记这个普通地板能访问到出口。
2.4传送器的处理逻辑
- 对于传送器的处理,需要检查传送器指向的位置,如果该位置也是传送器,则继续传送,直到找到普通地板或边界。
- 如果找到的普通地板是能够访问到出口的,则标记这个传送器也能访问到出口
- 如果是边界,则跳过这个方向
- 如果传送器形成了一个闭环(例如,一个向右的传送器后面紧跟着一个向左的传送器),也跳过这个方向。
2.5统计危险位置
- BFS完成后,遍历整个地图,统计所有不能访问到出口的位置(即
visited数组中值为False的位置)。 - 这些位置就是无论如何都无法到达出口的位置,即“危险位置”。 具体流程大概如下:
3.代码实现
def solution(N, M, data):
# Edit your code here
visited = [[False] * M for _ in range(N)]
# 找到出口位置
queue = []
for i in range(N):
for j in range(M):
if data[i][j] == 'O':
queue.append((i, j))
visited[i][j] = True
# 定义方向数组,用于处理普通移动
directions = {
'U': (-1, 0),
'D': (1, 0),
'L': (0, -1),
'R': (0, 1)
}
# 广度优先搜索
while queue:
x, y = queue.pop(0)
for direction, (dx, dy) in directions.items():
nx, ny = x + dx, y + dy
# 检查是否在边界内
if 0 <= nx < N and 0 <= ny < M:
# 是否是传送器
if data[nx][ny] in directions:
# 处理传送器
tx, ty = nx, ny
reverse = False
while data[tx][ty] in directions:
dx, dy = directions[data[tx][ty]]
tx += dx
ty += dy
if not (0 <= tx < N and 0 <= ty < M) or (tx == nx and ty == ny):
reverse = True
break
if 0 <= tx < N and 0 <= ty < M and visited[tx][ty] and not reverse:
queue.append((nx, ny))
visited[nx][ny] = True
elif not visited[nx][ny]:
queue.append((nx, ny))
visited[nx][ny] = True
else:
continue
# 统计危险位置数量
danger_count = 0
for i in range(N):
for j in range(M):
if not visited[i][j] and data[i][j] != '#':
danger_count += 1
return danger_count
4.心得总结
就我个人而言,我觉得我刷题的速度是非常缓慢的,可能是对数据结构和算法掌握的不够扎实的缘故,因为我大学是人工智能专业,学校对这方面的要求不高。有了AI刷题的帮助,确实帮了很大的忙。
不过我是觉得很多算法题目的流程都是差不多的,题目会给你一定的要求和限制,然后让你将代码写出来,这要求我们不仅要理解算法的一般流程,还要能够灵活应对特殊情况
还有一些问题想问问大家,从就业的角度来讲,刷题是不是很重要呢?