我使用0,1数组实现了一个迷宫。入口和目标在迷宫中得到修复。进入始终是迷宫的0,0点。目标始终是迷宫的m-1,n-1点。我现在使用广度优先搜索算法,但速度不够好。特别适用于大型迷宫(100 * 100左右)。有人可以帮我解决这个算法吗?
这是我的解决方案:
queue = []
position = start_node
mark_tried(position)
queue << position
while(!queue.empty?)
p = queue.shift #pop the first element
return true if maze.goal?(p)
left = p.left
visit(queue,left) if can_visit?(maze,left)
right = p.right
visit(queue,right) if can_visit?(maze,right)
up = p.up
visit(queue,up) if can_visit?(maze,up)
down = p.down
visit(queue,down) if can_visit?(maze,down)
end
return false
can_visit?方法检查节点是否在迷宫内,节点是否被访问,节点是否被阻塞。
答案 0 :(得分:6)
最糟糕的答案可能。
1)走到前面,直到你无法移动
2)左转
3)冲洗并重复。
如果你做到了,那就结束了。
更好的解决方案。
遍历迷宫,保留2个开放和封闭节点列表。使用着名的A-Star算法 选择评估下一个节点并丢弃作为死胡同的节点。如果打开列表中的节点用完,则没有退出。
答案 1 :(得分:3)
这是一个简单的算法,应该快得多:
从开始/目标移动到第一个交叉点。您可以忽略该交汇点与开始/目标之间的任何内容。
找到迷宫中死角的所有地方(它们有三面墙)。移回下一个交汇点并从搜索树中取出此路径。
以这种方式移除所有死角之后,应该留下一条路径(如果有多种方法可以达到目标,则为几条路径。)
答案 2 :(得分:2)
我不会在那里使用AStar算法,除非我真的需要,因为这可以通过一些简单的“着色”来完成。
# maze is a m x n array
def canBeTraversed(maze):
m = len(maze)
n = len(maze[0])
colored = [ [ False for i in range(0,n) ] for j in range(0,m) ]
open = [(0,0),]
while len(open) != 0:
(x,y) = open.pop()
if x == m-1 and y == n-1:
return True
elif x < m and y < n and maze[x][y] != 0 not colored[x][y]:
colored[x][y] = True
open.extend([(x-1,y), (x,y-1), (x+1,y), (x,y+1)])
return False
是的,这是愚蠢的,是的,它是面包和所有的。
这是A *实施
def dist(x,y):
return (abs(x[0]-y[0]) + abs(x[1]-y[1]))^2
def heuristic(x,y):
return (x[0]-y[0])^2 + (x[1]-y[1])^2
def find(open,f):
result = None
min = None
for x in open:
tmp = f[x[0]][x[1]]
if min == None or tmp < min:
min = tmp
result = x
return result
def neighbors(x,m,n):
def add(result,y,m,n):
if x < m and y < n: result.append(y)
result = []
add(result, (x[0]-1,x[1]), m, n)
add(result, (x[0],x[1]-1), m, n)
add(result, (x[0]+1,x[1]), m, n)
add(result, (x[0],x[1]+1), m, n)
return result
def canBeTraversedAStar(maze):
m = len(maze)
n = len(maze[0])
goal = (m-1,n-1)
closed = set([])
open = set([(0,0),])
g = [ [ 0 for y in range(0,n) ] for x in range(0,m) ]
h = [ [ heuristic((x,y),goal) for y in range(0,n) ] for x in range(0,m) ]
f = [ [ h[x][y] for y in range(0,n) ] for x in range(0,m) ]
while len(open) != 0:
x = find(open,f)
if x == (m-1,n-1):
return True
open.remove(x)
closed.add(x)
for y in neighbors(x,m,n):
if y in closed: continue
if y not in open:
open.add(y)
g[y[0]][y[1]] = g[x[0]][x[1]] + dist(x,y)
h[y[0]][y[1]] = heuristic(y,goal)
f[y[0]][y[1]] = g[y[0]][y[1]] + h[y[0]][y[1]]
return True
这是我的(简单)基准代码:
def tryIt(func,size, runs):
maze = [ [ 1 for i in range(0,size) ] for j in range(0,size) ]
begin = datetime.datetime.now()
for i in range(0,runs): func(maze)
end = datetime.datetime.now()
print size, 'x', size, ':', (end - begin) / runs, 'average on', runs, 'runs'
tryIt(canBeTraversed,100,100)
tryIt(canBeTraversed,1000,100)
tryIt(canBeTraversedAStar,100,100)
tryIt(canBeTraversedAStar,1000,100)
哪个输出:
# For canBeTraversed
100 x 100 : 0:00:00.002650 average on 100 runs
1000 x 1000 : 0:00:00.198440 average on 100 runs
# For canBeTraversedAStar
100 x 100 : 0:00:00.016100 average on 100 runs
1000 x 1000 : 0:00:01.679220 average on 100 runs
显而易见的是:要让A *顺利运行需要进行大量优化,我没有费心去追求......
我会说:
当你说得太多时,你在谈论多长时间?真的是一个100x100网格很容易被蛮力解析它是一个笑话:/
答案 3 :(得分:0)
我会用AStar实现解决这个问题。如果你想要更高的速度,你可以优化只从结点生成节点而不是每个瓦片/方块/步骤。
答案 4 :(得分:0)
您可以使用的方法无需访问迷宫中的所有节点,如下所示:
这不仅可以确定是否有路径,还可以显示迷宫中可能的最短路径。
你不需要回溯,所以它的O(迷宫室的数量)