繁体   English   中英

使用 BFS 从起点到终点的最短路径

[英]Shortest path from Start to end point using BFS

如果存在从表示为S的给定起点到端点E的最短路径,我想显示最短路径。 我有一个矩阵,其值为0表示没有路径, 1表示访问的有效路径。 我可以按行和按列访问,但不能按对角线方式访问。 现在使用 BFS,我可以使用以下代码将最短路径值作为整数获取:

public static void main(String[] args) {

    int r = findShortestPathBFS(new char[][] { "0001110011".toCharArray(), "1111011110".toCharArray(),
            "0110001010".toCharArray(), "S010101011".toCharArray(), "1110111E01".toCharArray() }, 3, 0);
    System.out.println(r);
}

private static int findShortestPathBFS(char arr[][], int startX, int startY) {
    if (arr[startX][startY] == 'E')
        return 0;
    int moveX[] = new int[] { 0, 0, 1, -1 };
    int moveY[] = new int[] { 1, -1, 0, 0 };
    boolean visited[][] = new boolean[arr.length][arr[0].length];
    Queue<QNode> qNodes = new LinkedList<>();
    qNodes.add(new QNode(startX, startY, 0));
    while (!qNodes.isEmpty()) {
        QNode currNode = qNodes.remove();
        int currX = currNode.x;
        int currY = currNode.y;
        int currDistance = currNode.distance;
        visited[currX][currY] = true;
        // System.out.println(arr[currX][currY]);
        if (arr[currX][currY] == 'E')
            return currDistance;

        for (int i = 0; i < moveX.length; i++) {
            int newX = currX + moveX[i];
            int newY = currY + moveY[i];

            if (newX >= 0 && newX < arr.length && newY >= 0 && newY < arr[0].length && !visited[newX][newY]
                    && arr[newX][newY] != '0') {
                qNodes.add(new QNode(newX, newY, currDistance + 1));
            }
        }

    }

    return -1;
}

private static class QNode {
    int x;
    int y;
    int distance;

    QNode(int x, int y, int distance) {
        this.x = x;
        this.y = y;
        this.distance = distance;
    }
}

在这个例子中,输入是:

0001110011
1111011110
0110001010
S010101011
1110111E01

[3,0]是我的起点, [4,7]是我的目的地,值为E

上面的代码将16打印为最短路径。 但是如果无法到达目的地,我想打印这样的实际路径(如果存在或not exists

上述代码的预期输出:

000***0011
11**0**110
01*000*010
S0*010*011
***011*E01

在这里,我想使用带有*有效路径路线再次打印矩阵。 如何在我的代码中实现这一点,或者是否有更好的方法来解决这个问题?

你可以在你的类 QNode 中有一个名为 prev 的字段来跟踪它访问的前一个节点,当你完成搜索时,你可以通过跟随 prev 链接来跟踪你的路径。

代码将是:

  private static Queue<QNode> qNodes;
  private static QNode endNode;
  public static void main(String[] args) {
    char[][] M = new char[][] { "0001110011".toCharArray(), "1111011110".toCharArray(),
            "0110001010".toCharArray(), "S010101011".toCharArray(), "1110111E01".toCharArray() };
    int r = findShortestPathBFS(M, 3, 0);
    while ( endNode.prev != null && M[endNode.prev.x][endNode.prev.y] != 'S') {
       M[endNode.prev.x][endNode.prev.y] = '*';
       endNode = endNode.prev;
    }
    for ( char[] arr : M )
      System.out.println(Arrays.toString(arr));
  }

  private static int findShortestPathBFS(char arr[][], int startX, int startY) {
      if (arr[startX][startY] == 'E')
          return 0;
      int moveX[] = new int[] { 0, 0, 1, -1 };
      int moveY[] = new int[] { 1, -1, 0, 0 };
      boolean visited[][] = new boolean[arr.length][arr[0].length];
      qNodes = new LinkedList<>();
      qNodes.add(new QNode(startX, startY, 0, null));
      while (!qNodes.isEmpty()) {
          QNode currNode = qNodes.remove();
          int currX = currNode.x;
          int currY = currNode.y;
          int currDistance = currNode.distance;
          visited[currX][currY] = true;
          // System.out.println(arr[currX][currY]);
          if (arr[currX][currY] == 'E') {
            endNode = currNode;
            return currDistance;
          }

          for (int i = 0; i < moveX.length; i++) {
              int newX = currX + moveX[i];
              int newY = currY + moveY[i];

              if (newX >= 0 && newX < arr.length && newY >= 0 && newY < arr[0].length && !visited[newX][newY]
                      && arr[newX][newY] != '0') {
                  qNodes.add(new QNode(newX, newY, currDistance + 1, currNode));
              }
          }
      }
      return -1;
  }
    
  private static class QNode {
      int x;
      int y;
      int distance;
      QNode prev;

      QNode(int x, int y, int distance, QNode prev) {
          this.x = x;
          this.y = y;
          this.distance = distance;
          this.prev = prev;
      }
  }

看到我将队列移到外面并使用一个名为 endNode 的节点来跟踪井端节点,然后在搜索该 endNode 是否为空后,即如果找到,则使用其上一个链接进行跟踪,直到它为空。 从语句中可以看出,起始节点为空: qNodes.add(new QNode(startX, startY, 0, null));

输出是:

[0, 0, 0, *, *, *, 0, 0, 1, 1]
[1, 1, *, *, 0, *, *, 1, 1, 0]
[0, 1, *, 0, 0, 0, *, 0, 1, 0]
[S, 0, *, 0, 1, 0, *, 0, 1, 1]
[*, *, *, 0, 1, 1, *, E, 0, 1]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM