A *找到第二条最短路径

时间:2014-05-13 05:20:34

标签: algorithm a-star

我正在尝试使用A *寻路算法实现第二个,最好是第n个最短路径。我已经实现了最短的路径:

while(open.length > 0) {
    max = worldSize;
    min = -1;
    for(i in open) {
        if(open[i].f < max) {
            max = open[i].f;
            min = i;
        }
    }

    node = open.splice(min, 1)[0];
    if(node.value === nodeEnd.value) {
        path = closed[closed.push(node)-1];
        do {
            result.push({x: path.x, y:path.y});
        } while(path = path.parent);
            open = closed = astar = [];
        result.reverse();
    } else {
        neighbors = findNeighbors(node.x, node.y);
        for(i = 0; i < neighbors.length; ++i) {
            path = newNode(node, neighbors[i]);
            if(!astar[path.value]) {
                path.g = node.g + manhattanDistance(neighbors[i], node);
                path.f = path.g + manhattanDistance(neighbors[i], nodeEnd);
                open.push(path);
                astar[path.value] = true;
            }

        }
        closed.push(node);
    }   
}

我该怎么办?我没有这方面的经验,甚至不能完全理解算法(目前仍在研究中)。谢谢。

3 个答案:

答案 0 :(得分:3)

所以这个问题一般都是NP难的。由于您只需要第二条最短路径,因此您可以轻松地进行操作。基本上,给定最短路径,您可以通过获取原始图形并从最短路径移除一条边来生成图形集合。因此,如果您有一条长度为N的最短路径,则在图G(E,N)上,您最终得到N个G(E-1,V)图。现在你在每个图上运行A *,最短的一个是你的第二个最短路径,就像它是最短路径,它与原始最短路径至少有一条边不同。

这也说明了为什么NP在实践中很难。如果我想要第三条最短路径,我必须按照以下步骤从两条最短路径中的每条路径中删除一条边,并且这些对的数量呈指数增长。 N-> N ^ 2-> N ^ 3等

答案 1 :(得分:0)

if(node.value === nodeEnd.value)是搜索终止条件。这意味着该算法从头到尾找到了一些路径。 A *的本质,特别是启发式函数(admissability and consistency)的属性可以保证第一次到达终止条件时为您提供最短的路径。

此外,可接受和一致的启发式方法还保证从始至终的所有可能路径始终从最短到最长检查

因此,为了获得第N个最近路径,您只需要允许搜索算法继续N-1次,例如

hit_count = 0
while(open.length > 0) {
    // same as before
    if(node.value === nodeEnd.value) {
          path = closed[closed.push(node)-1];
          hit_count += 1;
          if (hit_count == N - 1) {
              do {
                  result.push({x: path.x, y:path.y});
              } while(path = path.parent);
              open = closed = astar = [];
              result.reverse();
          }
    }
    else { 
         // same as before
    }
}

请注意,这种方法将产生与新路径长度相同的路径,即,如果您有两条相同长度的路径,其中一条路径将报告为最短路径,其他路径报告为第二条路径最短路径,具体取决于实施细节。

如果你想考虑长度相同的所有路径&#34;相同的&#34;,那么&#34; second-shortest&#34;实际上长于最短,只需将hit_count += 1替换为

// Don't forget to initialize last_found_path_length outside the loop to zero
if (path.length() != last_found_path_length) {
    last_found_path_length = path.length();
    hit_count += 1
}

请注意,您还没有指定它是什么语言(感觉就像Javascript),因此这里的示例可能包含语法错误或引用缺少的方法。但我希望这种方法很明确。

答案 2 :(得分:0)

近似解决方案是多次运行A *算法,但需要注意以下几点:

  • 找到当前最短路径后
  • 标记结束节点之前的节点
  • 下次运行算法时,请勿允许使用该节点,例如将它的path.f值设置为无穷大或巨大的东西。或者当它是当前节点的邻居时,不要将它添加到打开列表中。
  • 新发现的路径将是下一个最短路径

几点说明:

  • 这是近似值
  • 在连接到终端的所有节点循环完毕后,它将无法工作。
  • 在具有复杂路径和障碍的地形中,您可能会切断可能的路线
  • 如果可以通过在路径查找算法中做出决定来实现下一条最短路径,则无法捕获它。捕获你必须以所描述的方式循环遍历整个路径,一次不允许一个节点并采用所有可能的计算路径的最短路径 - 随着节点数量的增加,这将变得一团糟并且失去控制
希望有所帮助。