简体   繁体   English

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

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

I want to display the shortest path if exists from the given starting point represented as S to endpoint E .如果存在从表示为S的给定起点到端点E的最短路径,我想显示最短路径。 I have a matrix with value 0 indicating no path and 1 indicating a valid path to visit.我有一个矩阵,其值为0表示没有路径, 1表示访问的有效路径。 I can visit row-wise and column-wise but not diagonal way.我可以按行和按列访问,但不能按对角线方式访问。 Now using BFS I can get the shortest path value as an integer using the below code:现在使用 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;
    }
}

In this example by input is:在这个例子中,输入是:

0001110011
1111011110
0110001010
S010101011
1110111E01

[3,0] is my starting point and [4,7] is my destination with value E [3,0]是我的起点, [4,7]是我的目的地,值为E

The above code prints 16 as shortest path.上面的代码将16打印为最短路径。 But I want to print the actual path like this if present or not exists if not possible to reach destination.但是如果无法到达目的地,我想打印这样的实际路径(如果存在或not exists

Expected output for above code:上述代码的预期输出:

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

Here I want to print the matrix again with valid path route with * .在这里,我想使用带有*有效路径路线再次打印矩阵。 How to achieve this in my code or is there a better approach to solve this?如何在我的代码中实现这一点,或者是否有更好的方法来解决这个问题?

You could have a field called prev in your class QNode to track the previous node it visited and when you finished the search, you can track your path by following the prev link.你可以在你的类 QNode 中有一个名为 prev 的字段来跟踪它访问的前一个节点,当你完成搜索时,你可以通过跟随 prev 链接来跟踪你的路径。

The code would be :代码将是:

  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;
      }
  }

See that I moved the queue outside and used a node called endNode to track the well End Node, and then after search if that endNode is not null ie if it is found, follow through using its prev link until it is null.看到我将队列移到外面并使用一个名为 endNode 的节点来跟踪井端节点,然后在搜索该 endNode 是否为空后,即如果找到,则使用其上一个链接进行跟踪,直到它为空。 It would be null for the start node as you can see from the statement : qNodes.add(new QNode(startX, startY, 0, null));从语句中可以看出,起始节点为空: qNodes.add(new QNode(startX, startY, 0, null));

Output is :输出是:

[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