简体   繁体   English

有人可以帮助获得障碍的最短路径吗?

[英]Can someone help to get Shortest Path with Obstacles?

I have a 2D matrix.我有一个二维矩阵。 Given a 2D matrix where some of the elements are filled with '1' and the rest of the elements are filled with '0', except 2 elements, of which one is S (start point) and D (endpoint).给定一个二维矩阵,其中一些元素用“1”填充,元素的 rest 用“0”填充,除了 2 个元素,其中一个是 S(起点)和 D(终点)。 Here '0' means you cannot traverse to that particular point.这里的“0”表示您无法遍历到该特定点。 From a cell you can either traverse to left, right, up or down.您可以从一个单元格向左、向右、向上或向下遍历。 Given two points in the matrix find the shortest path between these points.给定矩阵中的两个点,找到这些点之间的最短路径。

One of the shortest paths (from S to D both exclusive) is: [(3, 2), (3, 1), (2, 1), (2, 0)].最短路径之一(从 S 到 D 都互斥)是:[(3, 2), (3, 1), (2, 1), (2, 0)]。 Return null if there is no path between S and D.如果 S 和 D 之间没有路径,则返回 null。

I have writtes a piece of code which returns the distance to reach from S to D, my method returns int but how to return as expected output?我编写了一段代码,它返回从 S 到 D 的距离,我的方法返回 int 但如何按预期返回 output? My code:我的代码:


public class ShortestPath {

     public static void main(String args[])
        {
            char[][] matrix = {
                {'S', '0', '1', '1'},
                {'1', '1', '0', '1'},
                {'0', '1', '1', '1'},
                {'1', '0', 'D', '1'}
            };

            int path = pathExists(matrix);

           System.out.println(path);
        }

    private static int pathExists(char[][] matrix) {

        Node source = new Node(0, 0, 0);
        Queue<Node> queue = new LinkedList<Node>();

        queue.add(source);

        while(!queue.isEmpty()) {
            Node poped = queue.poll();

            if(matrix[poped.x][poped.y] == 'D' ) {
                return poped.distanceFromSource;
            }
            else {
                matrix[poped.x][poped.y]='0';

                List<Node> neighbourList = addNeighbours(poped, matrix);
                queue.addAll(neighbourList);
            }   
        }
        return -1;
    }

    private static List<Node> addNeighbours(Node poped, char[][] matrix) {

        List<Node> list = new LinkedList<Node>();

        if((poped.x-1 > 0 && poped.x-1 < matrix.length) && matrix[poped.x-1][poped.y] != '0') {
            list.add(new Node(poped.x-1, poped.y, poped.distanceFromSource+1));
        }
        if((poped.x+1 > 0 && poped.x+1 < matrix.length) && matrix[poped.x+1][poped.y] != '0') {
            list.add(new Node(poped.x+1, poped.y, poped.distanceFromSource+1));
        }
        if((poped.y-1 > 0 && poped.y-1 < matrix.length) && matrix[poped.x][poped.y-1] != '0') {
            list.add(new Node(poped.x, poped.y-1, poped.distanceFromSource+1));
        }
        if((poped.y+1 > 0 && poped.y+1 < matrix.length) && matrix[poped.x][poped.y+1] != '0') {
            list.add(new Node(poped.x, poped.y+1, poped.distanceFromSource+1));
        }       
        return list;
    }
}
class Node {
    int x;
    int y;
    int distanceFromSource;

    Node(int x, int y, int dis) {
        this.x = x;
        this.y = y;
        this.distanceFromSource = dis;
    }
}

You are essentially implementing BFS (Breadth first search) to detect the existence of a path from the source (S) to the destination (D).您实际上是在实施 BFS(广度优先搜索)来检测从源 (S) 到目标 (D) 的路径是否存在。 All you need to trace the path is maintain a parent Node in your Node definition.跟踪路径所需的只是在节点定义中维护一个父节点。

Set the starting node's parent to null.将起始节点的父节点设置为 null。 Then, as your discover nodes in your BFS from the current node, set the parent of the discovered node to the current node.然后,当您从当前节点发现 BFS 中的节点时,将已发现节点的节点设置为当前节点。

Now, if your search is successful (ie you hit D in your search), just traverse the chain of parent nodes backwards from D until you hit S, throwing the visited parents into a stack.现在,如果您的搜索成功(即您在搜索中点击了 D),只需从 D 向后遍历父节点链,直到您点击 S,将访问过的父节点放入堆栈中。

Finally just keep popping the stack until it turns empty to get the nodes on the path from S to D.最后,继续弹出堆栈,直到它变空以获取从 S 到 D 路径上的节点。

you are getting only the distance because you are only returning the distance between source and Destination.你得到的只是距离,因为你只返回源和目的地之间的距离。 follow these to solve and print the route as well;按照这些解决并打印路线;

algo 1:-算法1:-

    just print the node value when you are updating the distance calculation. 

algo 2:-算法2:-

     1. create a queue to store the nodes. 
     2. insert the  node point of S to queue
     3. keep adding to the node value to queue when you are adding the value to distance. unless reaching to 'D'
     4. now just print the nodes from the queue which will print the path structure. 
class Cello {
    int row;
    int col;
    public Cello(int rowIndex, int colIndex) {
        super();
        this.row = rowIndex;
        this.col = colIndex;
    }   

     @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Cello cell = (Cello) o;
            return row == cell.row &&
                    col == cell.col;
        }

        @Override
        public int hashCode() {
            return Objects.hash(row, col);
        }
}   



public class ShortestPathWithParentChildMap {

    public static void main(String[] args) {
        char[][] grid2 = {{'S', '0', '1', '1'},
                         {'1', '1', '0', '1'},
                         {'0', '1', '1', '1'},
                         {'1', '0', 'D', '1'}};


        List<int[]> path = shortestPath(grid2);

         System.out.println("Path length:" + (path.size() - 1));
            path.stream().forEach(i -> {
                System.out.println("{" + i[0] + "," + i[1] + "}");
            });
    }

    private static void bfs(char[][] grid, Cello start, List<int[]> path) {

         int[] xDirs = new int[] {0,0,1, -1};
          int[] yDirs = new int[] {1,-1, 0, 0};

            Queue<Cello> bfsQueue = new LinkedList<>();
            bfsQueue.add(start);
            HashMap<Cello, Cello> parentMap = new HashMap<>();
            boolean[][] visited = new boolean[grid.length][grid[0].length];
            Cello endCell = null;
            while(!bfsQueue.isEmpty()) {
                boolean flag = false;
                Cello from = bfsQueue.poll();

                for (int k = 0; k < xDirs.length; ++k) {
                    int nextX = from.row + xDirs[k];
                    int nextY = from.col + yDirs[k];

                    if (nextX < 0 || nextX >= grid.length || nextY < 0 
                            || nextY >= grid[0].length || grid[nextX][nextY] == '0' 
                            || visited[nextX][nextY]) {
                        continue;
                    }

                    visited[nextX][nextY] = true;
                    Cello nextCell = new Cello(nextX, nextY);
                    bfsQueue.add(nextCell);
                    //we need a way to determine from where we have reached here
                    //storing the child to parent mapping, this will be used to retrieve the entire path
                    parentMap.put(nextCell, from);
                    //if (grid[nextX][nextY] == 'E') 
                    if (grid[nextX][nextY] == 'D') {
                        endCell = new Cello(nextX, nextY);
                        flag = true;
                        break;
                    }
                }
                if (flag) {
                    break;
                }
            }
            Stack<Cello> stack = new Stack<>();
            stack.push(endCell);

            //build the path from destination to source
            while (true) {
                Cello fromCell = parentMap.get(endCell);
                stack.push(fromCell);
                if (fromCell == start) break;
                endCell = fromCell;
            }
           //reverse the above path and convert as List<int[]>
            while (!stack.isEmpty()) {
                Cello p = stack.pop();
                path.add(new int[] {p.row, p.col});
            }
    }

    private static List<int[]> shortestPath(char[][] grid) {
        ArrayList<int[]> path = new ArrayList<>();
        for (int i = 0; i < grid.length; ++i) {
            for (int j = 0; j < grid[0].length; ++j) {
                if (grid[i][j] == 'S') {
                    bfs(grid, new Cello(i, j), path);
                }
            }
        }
        return path;
    }

}

Output is:
Path length:5
{0,0}
{1,0}
{1,1}
{2,1}
{2,2}
{3,2}

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

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