逃离监狱 - 找到最短的路

时间:2014-05-20 20:20:15

标签: java algorithm graph graph-algorithm

我已经完成了一项任务,我必须逃离迷宫。目标是找到最短路。我做了一些研究,似乎有两种解决问题的策略:Depth-first searchBreadth-first search,其中第一个从根开始(迷宫中的起点)并尽可能地探索回溯之前的每个分支,第二个分支从根节点开始并检查所有相邻节点。然后,对于每个这些邻居节点依次检查它们未被访问的邻居节点,等等。

我已经实现了两种算法(非递归实现),这些算法将一直持续到找到结束:

/**
 * A non-recursive implementation of DFS
 * @param maze
 */
void solveUsingDepthFirst(IMaze maze) {
    Stack<IMazePosition> candidates = new Stack<IMazePosition>();
    //insert start position
    candidates.push(maze.getStartPosition());

    IMazePosition currentPosition;
    IMazePosition nextPosition;
    while (!candidates.empty()) {
        currentPosition = candidates.pop();

        if (maze.isMazeSolved(currentPosition)) break;

        //mark the current position
        maze.markPosition(currentPosition, maze.getPathMark());
      // maze.printMaze();
        // Check for possible ways to go
        nextPosition = currentPosition.north();
        if (maze.canMove(nextPosition)) candidates.push(nextPosition);
        nextPosition = currentPosition.east();
        if (maze.canMove(nextPosition)) candidates.push(nextPosition);
        nextPosition = currentPosition.south();
        if (maze.canMove(nextPosition)) candidates.push(nextPosition);
        nextPosition = currentPosition.west();
        if (maze.canMove(nextPosition)) candidates.push(nextPosition);
    }

    System.out.println(!candidates.empty() ? "Done" : "Sorry, could not do it");
    maze.printMaze();
}

/**
 * A non-recursive implementation of BFS
 * @param maze
 */
void solveUsingBreadthFirst(IMaze maze) {
    LinkedList<IMazePosition> candidates = new LinkedList<IMazePosition>();
    //insert start position
    candidates.add(maze.getStartPosition());

    IMazePosition currentPosition;
    IMazePosition nextPosition;
    while (!candidates.isEmpty()) {
        currentPosition = candidates.removeFirst();

        if (maze.isMazeSolved(currentPosition)) break;

        //markPosition the current position
        maze.markPosition(currentPosition, maze.getPathMark());
     //   maze.printMaze();

        // Check for possible ways to go
        nextPosition = currentPosition.north();
        if (maze.canMove(nextPosition)) candidates.add(nextPosition);
        nextPosition = currentPosition.east();
        if (maze.canMove(nextPosition)) candidates.add(nextPosition);
        nextPosition = currentPosition.south();
        if (maze.canMove(nextPosition)) candidates.add(nextPosition);
        nextPosition = currentPosition.west();
        if (maze.canMove(nextPosition)) candidates.add(nextPosition);
    }

    System.out.println(!candidates.isEmpty() ? "Done" : "Sorry, could not do it");
    maze.printMaze();
}

地图(或迷宫)表示为char[][]。 MazePosition是坐标的表示:

public MazePosition(int x, int y) {
    this.x = x;
    this.y = y;
}

现在有了这段代码,我可以找到所有可能的路径,从头到尾,我能够找到,直到我第一次找到结束 - 是否可以假设最短的路径在其中? 鉴于我有可能的路径,我怎样才能找到最短的路径?并且,路径生成的代码是否有任何好处?我可以优化我已经拥有的任何例程。

另外,据我所知,没有&#34;漏洞&#34;在迷宫中,这意味着我总能坚持到墙上。

2 个答案:

答案 0 :(得分:1)

如果你有所有可能的路径,我愿意打赌最短路径就在其中。

正如Blender所提到的,在广泛的第一次搜索中,发现的第一个解决方案将属于最佳解决方案集(最短路径)。

如何找出候选人的路径有多长?将pathLength字段添加到MazePosition类,每次添加候选位置时都会增加它。当你到达日光时,该字段会告诉你你已经走了多少步。

没有出口的迷宫怎么样?也许你应该跟踪你去过的地方。

为了回答关于&#34;善良&#34;的问题。和&#34;优化&#34;我们需要知道你正在做什么约束。慢得多慢?这些迷宫有多大? 过早优化是万恶之源。

答案 1 :(得分:1)

深度优先不太可能找到最短的路线,除非只有少量可能的路线(并且你无法确认它是最短的路线)。

广度优先总是找到&#34; a&#34;最短的路线首先,假设您在每个步骤的每个节点增加相同的距离(可能有多条相等长度的路线)。

如果你进行了一次迭代而没有更多步骤,那么迷宫就不可能了。

记录实际路线的最简单方法可能就是“标记”&#39;每个位置都有远距离,然后当你到达出口时,你可以反复追踪路线(从完成到开始),反复踩到一个距离较小的相邻位置 - 直到你回到开始(当然,记录路线)。

根据迷宫的维度,如果你已经知道出口的位置,你可以通过从起点到终点先做宽度直到搜索重合来减少寻找路线所需的步数。 (如果那不被认为是&#34;作弊&#34;)。