如何实现遇障才换向的二维迷宫最短路径及路径输出
特殊行进规则二维迷宫最短路径实现(输出完整节点序列)
核心规则
- 仅支持上下左右4个移动方向
- 一旦选定移动方向启动直行,必须保持前进直到前方碰到墙体、边界等障碍物时,才允许切换方向,不得中途主动换向
- 迷宫元素定义:
x为起点,1为障碍物,0为可通行区域,g为终点 - 示例迷宫:
[[1, 1, 1, 1, 1] [1, x, 0, 0, 1] [1, 0, 0, 0, g] [1, 1, 1, 1, 1]]
该示例下符合规则的正确最短路径节点序列为:[(1,1), (2,1), (2,4)]
现有代码缺陷
你提供的基于Dijkstra的实现可正确计算最短路径长度,但没有维护节点间的前驱映射关系,因此无法回溯输出完整的路径节点序列。
改进思路
- 保留原算法核心逻辑:每次枚举当前节点的四个方向,直行到该方向下的最远可停靠点(即前方紧邻障碍物/边界的位置),作为可切换方向的相邻节点
- 新增
prev字典,记录每个可停靠节点的前驱停靠节点,作为路径回溯的依据 - 当Dijkstra算法首次弹出终点节点时,顺着
prev字典反向回溯所有停靠节点,反转后得到正序的完整路径
改进后完整可运行代码
import heapq from typing import List, Tuple, Dict, Optional def get_rule_compliant_path(maze: List[List], start: List[int], destination: List[int]) -> Optional[List[Tuple[int, int]]]: # 预处理迷宫:将x/g标记转换为可通行的0 processed_maze = [] for row in maze: new_row = [] for cell in row: if cell in ('x', '0', 'g'): new_row.append(0) else: new_row.append(1) processed_maze.append(new_row) start_node = tuple(start) dest_node = tuple(destination) row_count, col_count = len(processed_maze), len(processed_maze[0]) # 计算当前节点四个方向上的最远停靠点及直行步数 def calc_adjacent_stops(node: Tuple[int, int]) -> List[Tuple[int, Tuple[int, int]]]: adj_stops = [] curr_x, curr_y = node for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]: step_x, step_y = curr_x, curr_y step_len = 0 # 持续直行直到遇到不可通行的障碍或边界 while 0 <= step_x + dx < row_count and 0 <= step_y + dy < col_count and processed_maze[step_x + dx][step_y + dy] == 0: step_x += dx step_y += dy step_len += 1 # 跳过无有效移动的方向 if step_len > 0: adj_stops.append((step_len, (step_x, step_y))) return adj_stops # Dijkstra初始化 priority_heap = [(0, start_node)] visited_nodes = set() # 记录每个节点的前驱停靠点,用于路径回溯 prev_node_map: Dict[Tuple[int, int], Optional[Tuple[int, int]]] = {start_node: None} while priority_heap: curr_dist, curr_node = heapq.heappop(priority_heap) # 已处理过的节点直接跳过(Dijkstra保证第一次弹出的为最短路径节点) if curr_node in visited_nodes: continue # 到达终点时回溯生成完整路径 if curr_node == dest_node: path = [] trace_node = curr_node while trace_node is not None: path.append(trace_node) trace_node = prev_node_map[trace_node] # 反向回溯结果反转即为正序路径 return path[::-1] visited_nodes.add(curr_node) for step_len, adj_node in calc_adjacent_stops(curr_node): new_dist = curr_dist + step_len if adj_node not in visited_nodes: prev_node_map[adj_node] = curr_node heapq.heappush(priority_heap, (new_dist, adj_node)) # 无可达路径时返回空 return None
验证说明
对应用户提供的示例迷宫,调用时传入起点参数start=[1,1](对应迷宫中x的坐标)、终点参数destination=[2,4](对应迷宫中g的坐标),函数返回结果为[(1, 1), (2, 1), (2, 4)],与预期的正确路径完全匹配。
内容的提问来源于stack exchange,提问作者feedy
相关产品推荐
相关产品推荐

