如何在这种类型的迷宫中寻找最短路径

时间:2015-11-04 06:16:00

标签: algorithm path shortest-path breadth-first-search shortest

Red

Red Dot - Represents the initial location
Black Dot - Already occupied
Green - Free to occupy
Destination - Boundry of the matrix [which means either x = 0 or y = 0 or x = 8 or y = 8]

eg. 示例:

red dot一次只能放置一个动作,并且可以移动到附在其上的绿色六个圆圈中的一个。 计算这种迷宫中最短路径的最快方法是什么。

3 个答案:

答案 0 :(得分:4)

首先,你不需要Dijkstra,因为边的所有值都是相同的。您可以使用简单的BFSDFS算法。最坏的情况是相同的,但我会使用BFS,因为它具有更好的平均情况复杂性。但是,O(| V | + | E |)是你能到达这里的最快的,并且已经证实了。

如何表示图表?最好的方法是保留每个Node的邻居列表。您示例中的黑点不算作邻居。因此在您的示例中,每个节点将具有0(完全被黑点覆盖)到6个邻居。然后,您可以通过这些列表从任何节点获取任何地方。

BFS算法具有一个属性,它为每个节点分配一个层,这意味着它与起始节点的距离。从起点开始,当前图层将为0.然后,您只需跟踪当前图层中的所有节点(通常保留在队列中)并尝试找到它的邻居(来自其邻居列表),它们没有图层已分配并为其分配+1更高层。一旦找到你的节点(它仍然可以有x,y作为边界检查的属性(或属性bool边界)),在迷宫的边界处,你知道它就像你的图层值一样。如果你想打印确切的方式,你只需要找回(通过你的邻居列表),这符合每个步骤低-1层的条件。这将打印从头到尾的方式,但我相信你会在Stack数据结构的帮助下得到你的结果:)

答案 1 :(得分:3)

你所拥有的是一个“简单”的图形问题。图表连接是您的合法举措。起始节点是您的红点。要获得单个终端节点,请在给定的迷宫之外再创建一个圆圈;将所有实际出口节点连接到新的圆圈,移动成本为零。

现在,应用Dijkstra的算法。完成。

另一种查看问题的方法是使用递归。移动红点,将旧位置标记为黑色。从新职位重新出发。退出时返回(返回路径长度1)或没有合法移动(返回路径长度无限)。保持最短的已知路径。

那些让你没有被困住吗?

答案 2 :(得分:-1)

A *搜索算法

(距离: https://en.wikipedia.org/wiki/A*_search_algorithm

以下伪代码描述了算法[可疑 - 讨论]:

function A*(start,goal)
    ClosedSet := {}       // The set of nodes already evaluated.
    OpenSet := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
    Came_From := the empty map    // The map of navigated nodes.


    g_score := map with default value of Infinity
    g_score[start] := 0    // Cost from start along best known path.
    // Estimated total cost from start to goal through y.
    f_score := map with default value of Infinity
    f_score[start] := g_score[start] + heuristic_cost_estimate(start, goal)

    while OpenSet is not empty
       current := the node in OpenSet having the lowest f_score[] value
        if current = goal
            return reconstruct_path(Came_From, goal)

       OpenSet.Remove(current)
       ClosedSet.Add(current)
       for each neighbor of current
           if neighbor in ClosedSet 
               continue     // Ignore the neighbor which is already evaluated.
        tentative_g_score := g_score[current] + dist_between(current,neighbor) // length of this path.
        if neighbor not in OpenSet  // Discover a new node
            OpenSet.Add(neighbor)
        else if tentative_g_score >= g_score[neighbor] 
            continue        // This is not a better path.

        // This path is the best until now. Record it!
        Came_From[neighbor] := current
        g_score[neighbor] := tentative_g_score
        f_score[neighbor] := g_score[neighbor] + heuristic_cost_estimate(neighbor, goal)

return failure

function reconstruct_path(Came_From,current)
    total_path := [current]
    while current in Came_From.Keys:
        current := Came_From[current]
        total_path.append(current)
    return total_path

所以,据我所知 - 您可以将起始节点设置在红点位置\中心位置,目标节点设置为x = 0或y = 0或x = 8或y = 8(您可以制作4个函数调用,并采取最小值)

至于节点的启发式值 - 只需将黑色阻塞节点设置为非常高的启发式值,这将使它们无法访问,因此算法将绕过它们。