广度优先搜索解决迷宫问题

9

请问有人能够解释如何使用广度优先搜索(BFS)解决迷宫问题吗?我需要使用BFS找到迷宫中的最短路径,但是我感到非常困惑。

以下是我书中的伪代码:

void breadth_first_search(tree T) {
  queue!;
  node u, v;

  initialize(Q);
  v = root of T;
  visit v;
  enqueue(Q, v);

  while (!empty(Q)) {
    dequeue(Q, v);
    for (each child u of v) {
      visit u;
      enqueue(Q, u);
    }
  }
}

如果我有一个存储在二维矩阵中的迷宫,那么“根”(即起点)会在吗?


7
这是一个优秀的算法可视化演示(并与其他搜索算法进行比较),这里有源代码可用。 - Casey Kuball
2个回答

14

这是一个完整的BFS迷宫求解器。如果找到终点,它将返回完整的最短路径。在迷宫数组arr中:0表示未被探索的空间,5表示墙壁空间,9表示目标空间。空间在被访问后标记为-1

import java.util.*;

public class Maze {

  public static int[][] arr = new int[][] {
            {0,0,0,0,0,0,0,0,0},
            {5,5,5,0,0,0,0,0,0},
            {0,0,0,5,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,9},
    };

  private static class Point {
        int x;
        int y;
        Point parent;

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

        public Point getParent() {
            return this.parent;
        }

        public String toString() {
            return "x = " + x + " y = " + y;
        }
  }

  public static Queue<Point> q = new LinkedList<Point>();

    public static Point getPathBFS(int x, int y) {

        q.add(new Point(x,y, null));

        while(!q.isEmpty()) {
            Point p = q.remove();

            if (arr[p.x][p.y] == 9) {
                System.out.println("Exit is reached!");
                return p;
            }

            if(isFree(p.x+1,p.y)) {
                arr[p.x][p.y] = -1;
                Point nextP = new Point(p.x+1,p.y, p);
                q.add(nextP);
            }

            if(isFree(p.x-1,p.y)) {
                arr[p.x][p.y] = -1;
                Point nextP = new Point(p.x-1,p.y, p);
                q.add(nextP);
            }

            if(isFree(p.x,p.y+1)) {
                arr[p.x][p.y] = -1;
                Point nextP = new Point(p.x,p.y+1, p);
                q.add(nextP);
            }

             if(isFree(p.x,p.y-1)) {
                arr[p.x][p.y] = -1;
                Point nextP = new Point(p.x,p.y-1, p);
                q.add(nextP);
            }

        }
        return null;
    }


    public static boolean isFree(int x, int y) {
        if((x >= 0 && x < arr.length) && (y >= 0 && y < arr[x].length) && (arr[x][y] == 0 || arr[x][y] == 9)) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {

        Point p = getPathBFS(0,0);

         for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                System.out.print(arr[i][j]);
            }
            System.out.println();
        }

        while(p.getParent() != null) {
            System.out.println(p);
            p = p.getParent();
        }

    }

}

1
5和9是什么? - Core_Dumped

6

简短回答:是的

解释:

该伪代码将迷宫中的路径表示为树叶的路径。迷宫中的每个位置都是树上的一个节点,可以从那里到达的每个新位置都是该节点的子节点。

为了进行广度优先搜索,算法首先必须考虑长度为一的所有树路径,然后是长度为二等,直到到达结束点,这将导致算法停止,因为结束点没有孩子,结果为空队列。

该代码使用队列(Q)跟踪需要访问的节点。它首先将迷宫的起点设置为树的根,访问它(检查是否为结束点),然后从队列中删除根并重复每个子项的过程。通过这种方式,它以后序方式访问节点,即根、(每个根的子节点)、(第一个子节点的每个子节点)、(第二个子节点的每个子节点)等,直到到达结束点。

编辑:目前,当算法到达终点时,由于队列中存在其他节点,可能不会终止。您必须自己编写终止条件。


发布的算法更恰当地描述为树的广度优先遍历,因为没有进行比较/测试,并且迄今为止最短的路径没有被跟踪。如果找到搜索目标,则算法不会提前终止,因此将遍历整个树。将其应用于2D迷宫时,请记住“访问”节点应将其标记,然后您需要检查是否已将节点标记为避免永久循环(除非您定义了顺序,在这种情况下仅向一个方向排队)。 - jerry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接