【问题标题】:most efficient way to find a path between 2 nodes in a grid在网格中的 2 个节点之间找到路径的最有效方法
【发布时间】:2012-02-12 17:26:22
【问题描述】:

我一直对如何最好地解决这个特定问题感到好奇。我能找到的最接近问题的是管道游戏概念,see screenshot

我有一个 10x10 的网格。网格的每个矩形都可以连接到具有 1 到 4 条边(没有对角线,只有顶部、底部、左侧、右侧)的相邻字段 网格左侧可以有 10 个起点,每行一个,然后右 10 个端点在网格的每一行中也有 1 个。

现在我的问题是:找到从起点到任何终点的所有可能路径以及所有死路(有几个点连接到起点的路径)的最有效方法是什么?点但不连接到任何端点)?

我已经尝试了广度优先搜索算法来查找它们之间的所有路径,但是我可以尝试任何更好的替代方法吗?

【问题讨论】:

  • 您为什么要寻找替代方案?
  • 另一种自然的选择是深度优先搜索。然而,我同意@svick 的观点,即询问您为什么需要替代方案。
  • 我正在探索所有的可能性,主要是我只是好奇有什么可以解决这个问题。以及死胡同怎么样。可以安全地假设最好的方法是找到从每个正方形到至少一个起点的路径?
  • 使用这种格式的网格,听起来你根本不需要 BFS/DFS,因为找到两点之间最短路径的算法很简单(只要往前走,直到你在上面/下面下一点,然后分别向下/向上)。
  • what is the most efficient way to find all the possible paths 网格上任意两点之间的路径数不胜数...比较 left->right->left->right.... 所以很难找到所有路径...您应该将自己限制在最短路径或最多 k 条最短路径中,以获得恒定的 k

标签: java algorithm path-finding


【解决方案1】:

通常A* 比 BFS 快得多,用于在图上查找最短路径

A* 要求你有一个 admissible heuristic function [manhattan distance 启发式通常可以应用于网格],并且通常比 BFS 快得多,因为它被告知 - 所以它更喜欢调查更有可能的节点以找到更好的解决方案。

请注意,A* 也是完整的[找到一条路径,如果有一条路径],也是最优的[找到最短路径]。

编辑:
A* 还允许更多地权衡时间/性能:例如:通过使用 weighted A*,您将获得非最佳解决方案,但您可能会更快地获得它。

请注意,对于不知情的 A* [h=0],通过调用 A* 你会得到一个 dijkstra,这正是非加权边的 BFS

【讨论】:

  • 是的 A* 加上适当的启发式表现非常好
  • 这个问题根本没有谈论最短路径。因此,我认为使用 A* 没有任何意义。
  • 这正是我明确提到 A* 有利于寻找最短路径的原因。
【解决方案2】:

如果您从广度优先开始,您将首先收集长度为 1 的路径,然后是 2、3、4 等等。在从长度 k 到 k+1 的下一步中,仅在某个路径中尚未使用该端点时,才向某个路径添加一个端点。这可以保证您丢弃较少或同等最佳的路径。

除了原点,所有路径点都有一个明确的传入边缘。因此,作为数据结构,可以存储每个点的传入边(或 no_incoming)。 这会丢弃同样最优的路径。

案例:同样最优路径 同样的最佳路径可以在数据中表示为具有多个输入边的点。 从长度 k 到 k+1 收集所有新端点。

  • 如果候选端点存在于路径中,但不存在于新的 (k+1) 个长端点中,则它是次优路径,将被丢弃。递归失败。
  • 如果候选端点是新的,则会找到新的最佳路径。递归继续。
  • 如果候选端点仅存在于新端点中,则找到替代的最佳路径。递归也停止。

一点代码

public void determineAllPaths(Grid grid, Point origin) {
    this.grid = grid;
    this.origin = origin;
    grid.setOnPath(origin, null); // to, from
    Set<Point> priorEndPoints = Collections.singleton(origin);
    determinePaths(priorEndPoints);
}

private void determinePaths(Set<Point> priorEndPoints) {
    if (priorEndPoints.isEmpty())
        return;
    Set<Point> nextEndPoints = new HashSet<Point>();
    for (Point priorEndPoint : priorEndPoints) {
        for (Point nextEndPoint : priorEndPoint.naybours()) {
            if (grid.isOnPath(nextEndPoint)
                    && !nextEndPoints.contains(nextEndPoint)) {
                continue;
            }
            //if (nextEndPoints.contains(nextEndPoint)) {
            //    continue;
            //}
            grid.setOnPath(nextEndPoint, priorEndPoint); // to, from
            nextEndPoints.add(nextEndPoint);
        }
    }
    determinePaths(nextEndPoints);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-04
    • 2011-03-08
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多