可回溯已访问区域的全必经点迷宫最短路径求解方案咨询
迷宫跳跃寻路程序逻辑规划方案
一、需求规则梳理
- 移动方式:仅支持上下左右直线跳跃,每次必须跳过1个格子
- 禁区规则:
- 着陆点禁止为
|、—、I、=、. - 仅可跳过
|和—,无法跳过I或=
- 着陆点禁止为
- 路径要求:
- 从
S出发,必须遍历所有X后才能着陆E,着陆E即终止程序 - 允许回溯已着陆过的空间,最终返回最短路径的着陆点坐标顺序
- 从
二、核心问题与算法适配思路
你之前实现的Dijkstra/A*算法默认通过标记「已访问节点」避免循环,但这里允许回溯,核心修改点是扩展状态维度:
- 原算法仅以当前坐标作为状态标识,现在需要把「已收集的X坐标集合」加入状态。例如状态定义为
(x, y, collected_xs),其中collected_xs是已到达的X坐标集合。 - 这样即使回到同一个坐标,只要已收集的X集合不同,就属于不同状态,不会被过滤;同时通过状态去重,避免重复处理相同(坐标+X收集状态)的长路径。
三、具体实现步骤
1. 迷宫预处理
遍历迷宫数组,记录关键节点信息:
- 起点
S的坐标start_pos - 终点
E的坐标end_pos - 所有
X的坐标列表all_xs,统计总数量total_x
2. 状态与优先级队列配置
- 状态结构:
(当前路径长度, 当前坐标, 已收集X集合, 路径序列) - 使用小顶堆作为优先级队列,优先处理路径更短的状态(Dijkstra逻辑);若用A*优化,可加入启发式函数(比如当前坐标到E的曼哈顿距离 + 剩余未收集X的最小距离之和)提升搜索效率。
- 用字典
visited做状态去重,键为(x, y, frozenset(collected_xs))(集合转不可变类型实现哈希),值为该状态下的最短路径长度。若新状态的路径长度大于已记录值,直接跳过。
3. 移动逻辑实现
对当前坐标(x, y),遍历四个方向(上、下、左、右):
- 计算中间格子坐标
(mid_x, mid_y)和目标着陆坐标(target_x, target_y) - 检查中间格子:必须是
|或—(符合可跳过规则) - 检查目标着陆格子:
- 不能是
|、—、I、=、. - 若目标是
E,必须满足len(collected_xs) == total_x(已收集所有X)
- 不能是
- 更新收集状态:若目标是
X且未被收集,将其加入collected_xs - 生成新状态,计算新路径长度和路径序列,检查
visited中是否存在更优路径,若没有则加入队列。
4. 终止条件
当处理到状态中目标坐标为E且已收集所有X时,返回该状态的路径序列,即为最短路径。
四、给定迷宫示例
maze = [ ["O","|","E","I","X","I","O"], ["—",".","=",".","—",".","—"], ["O","|","O","|","O","|","O"], ["=",".","—",".","=",".","—"], ["X","|","O","I","O","|","X"], ["—",".","=",".","—",".","="], ["O","|","S","|","O","|","O"], ]
内容的提问来源于stack exchange,提问作者aakhilv
相关产品推荐
相关产品推荐

