问题:在有障碍物的矩形网格上找到最接近多个目标的路径。仅允许向上/向下/向左/向右移动(无对角线)。我确实看到了this question and answers,and this,and that等。我没有看到有人使用或建议我的特定方法。我的做法是否有重大错误?
我最重要的约束是,如果你愿意,我可以很方便地将路径(或任何列表)表示为“堆栈”或“单链表”。也就是说,对顶部元素的恒定时间访问,O(n)用于反转。
显而易见的(对我而言)解决方案是使用曼哈顿距离启发式搜索从任何目标到起点的路径。从目标到起点的第一条路径是到达最近目标的最短路径(可能是其中之一),我不需要在跟踪它之前反转路径(它将是“正确的”顺序,起点在顶部,目标在最后)。
在伪代码中:
A*(start, goals) :
init_priority_queue(start, goals, p_queue)
return path(start, p_queue)
init_priority_queue(start, goals, q_queue) :
for (g in goals) :
h = manhattan_distance(start, g)
insert(h, g, q_queue)
path(start, p_queue) :
h, path = extract_min(q_queue)
if (top(path) == start) :
return path
else :
expand(start, path, q_queue)
return path(start, q_queue)
expand(start, path, q_queue) :
this = top(path)
for (n in next(this)) :
h = mahnattan_distance(start, n)
new_path = push(n, path)
insert(h, new_path, p_queue)
对我来说,用这种方式反转搜索似乎很自然。这里有想法吗?
另一个问题:假设我的优先级队列在具有相同优先级的元素上是稳定的(如果两个元素具有相同的优先级,则稍后插入的元素将更早出现)。我故意将我的next
保留在未定义之上:随机化返回矩形网格上可能的下一个图块的顺序似乎是一种非常便宜的方法,可以通过一个没有矩形区域的方式找到不可预测的,相当锯齿形的路径障碍,而不是沿着两条边缘(曲折路径在统计上更可能)。这是对的吗?
答案 0 :(得分:0)
就我所见,它在大O中正确有效(N log N,只要启发式是可接受且一致的,其中N =网格的单元格数,假设您使用其操作有效的优先级队列在日志N)。之字形也会起作用。
P.S。对于这些问题,有一个更有效的“优先级队列”在O(1)中工作。对于这类问题,我的意思是每对节点之间的有效距离是一个非常小的常数(在这个问题中为3)。
编辑:根据评论中的要求,以下是此问题的常量时间“优先级队列”的详细信息。
首先,将图形转换为下图:让图形中节点的电位(即网格中的单元格)为从节点到目标的曼哈顿距离(即启发式)。我们称节点i的潜力为P(i)。以前,在相邻单元之间存在边缘并且其权重为1.在修改的图中,权重w(i,j)变为w(i,j)-P(i)+ P(j)。这与A *为最优的证据完全相同,并且在启发式是可接受且一致的情况下以多项式时间终止。请注意,针对此问题的曼哈顿距离启发式算法既可接受又一致。
第一个关键观察是原始图中的A *与修改后的图中的Dijkstra完全相同。这是因为修改后的图中节点i的“值”恰好是距原点节点加P(i)的距离。第二个关键观察是我们转换图中每条边的权重是0或2.因此,我们可以通过使用“deque”(或双向链表)而不是普通队列来模拟A *:每当我们遇到权重为0的边缘,将其推到队列的前面,每当我们遇到权重为2的边缘时,将其推到队列的末尾。
因此,该算法模拟A *并在最坏的情况下以线性时间工作。