Python 加快Dijkstra';求解三维迷宫的s算法
我正在尝试编写一个Python脚本来解决3D迷宫问题,我正在使用Dijkstra的算法和优先级队列(包含在模块heapq中)来完成。以下是我的主要功能代码:Python 加快Dijkstra';求解三维迷宫的s算法,python,algorithm,3d,dijkstra,maze,Python,Algorithm,3d,Dijkstra,Maze,我正在尝试编写一个Python脚本来解决3D迷宫问题,我正在使用Dijkstra的算法和优先级队列(包含在模块heapq中)来完成。以下是我的主要功能代码: from heapq import * def dijkstra(start,end,vertices,obstacles): covered=[] s=vertices.index(s) currentVertex=s liveDistances={} for i in range(len(vert
from heapq import *
def dijkstra(start,end,vertices,obstacles):
covered=[]
s=vertices.index(s)
currentVertex=s
liveDistances={}
for i in range(len(vertices)):
liveDistances[i]=inf
liveDistances[s]=0
next=[[liveDistances[s],s]]
while next:
np,currentVertex=heappop(next)
covered.append(currentVertex)
for u in sons(vertices[currentVertex]):
v=vertices.index(u)
if v in covered:continue
if 1+liveDistances[currentVertex]<liveDistances[v]:
liveDistances[v]=1+liveDistances[currentVertex]
heappush(next,[liveDistances[v],v])
if liveDistances[vertices.index(e)]!=inf:
return liveDistances[vertices.index(e)]
else:
return "No path!"
来自heapq导入的*
def dijkstra(起点、终点、顶点、障碍物):
覆盖=[]
s=顶点。索引(s)
currentVertex=s
liveDistances={}
对于范围内的i(len(顶点)):
livedistance[i]=inf
livedistance[s]=0
下一步=[[liveDistances[s],s]]
下一步:
np,currentVertex=heappop(下一个)
covered.append(currentVertex)
对于子对象中的u(顶点[currentVertex]):
v=顶点。索引(u)
如果覆盖v:继续
如果1+liveDistances[currentVertex]您知道*搜索(“A星”)吗?这是对Dijkstra算法的修改,当你了解情况的几何学时,它会有很大的帮助。未经修改的Dijkstra假设任何边缘都可能是通往目标的一条非常短的道路的起点,但通常情况下,情况的几何结构不允许这样做,或者至少使其不太可能
基本的想法是,如果你想找到一条从丹佛到匹兹堡的最短路径,那么通往盐湖城的边缘不太可能有帮助。因此,通过向堆中的权重添加从该节点到目标的距离的下限来偏移权重——在这个2D示例中,这将是直线或大圆距离,因为没有实际道路可以比这短。这种启发式倾向于将错误的选择进一步推到堆中,因此它们通常永远不会被发现
不过,我无法证明你构建3D迷宫的方式是否适用于*搜索。我怀疑在这两行中会花费大量时间:
v=vertices.index(u)
if v in covered:continue
这两条线都是O(n)操作,其中n是图形中的顶点数
我建议将第一个替换为字典(从顶点名称映射到顶点索引),第二个替换为将covered
从列表更改为集合
这将使两种操作都达到O(1)级,并可使速度提高几个数量级。我最初的方法是使用一些基本的回溯:
boolean[][]已访问=新的boolean[h][w][d];
布尔foundPath=false;
公共无效路径(整数y、整数x、整数z){
访问[y][x][z]=真;
如果(x==targetx&&y==target&&z==targetz){
foundPath=true;
返回;
}
if(!visted[y-1][x][z]&&&!foundPath)//if up
路径(y-1,x,z);
如果(!已访问[y+1][x][z]&&&!foundPath)//如果已关闭
路径(y+1,x,z);
如果(!visted[y][x-1][z]&&&!foundPath)//如果离开
路径(y,x-1,z);
如果(!已访问[y][x+1][z]&&&!foundPath)//如果正确
路径(y,x+1,z);
if(!visted[y][x][z+1]&&&!foundPath)//if forward
路径(y,x,z+1);
if(!visted[y][x][z-1]&&&!foundPath)//if backward
路径(y,x+1,z-1);
if(foundPath)返回;
访问[y][x][z]=错误;
}
不,这不正常。我无法通过查看代码发现问题,但如果您提供完整的代码和地图,我可能会帮助您。选择dijkstra而不是BFS还有什么特别的原因吗?我只是更熟悉dijkstra的,因为dijkstra和BFS非常相似,我不认为BFS会有很大的提高。我算法的其余部分只是返回任意给定点的相邻网格点的函数sons,因此我认为这没有什么区别。如果有人想运行代码并自行测试,他们将需要剩余的资源。我尝试了使用欧几里德距离作为启发式的*搜索,虽然在30x30x30没有墙壁的迷宫上,它并没有做出很大的改变。解决这个问题仍然需要一分钟以上的时间。当有更多的墙时,这会有不同。它找不到最短路径,是吗?假设有多个解决方案,不,通常是DFS