【问题标题】:Can someone help to get Shortest Path with Obstacles?有人可以帮助获得障碍的最短路径吗?
【发布时间】:2020-04-17 07:03:03
【问题描述】:

我有一个二维矩阵。 给定一个二维矩阵,其中一些元素用“1”填充,其余元素用“0”填充,除了 2 个元素,其中一个是 S(起点)和 D(终点)。这里的“0”表示您不能遍历到该特定点。您可以从一个单元格向左、向右、向上或向下遍历。给定矩阵中的两个点,找出这些点之间的最短路径。

最短路径之一(从 S 到 D 都互斥)是:[(3, 2), (3, 1), (2, 1), (2, 0)]。如果 S 和 D 之间没有路径,则返回 null。

我编写了一段代码,它返回从 S 到 D 的距离,我的方法返回 int 但如何返回预期的输出? 我的代码:


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

【问题讨论】:

    标签: java algorithm shortest-path breadth-first-search


    【解决方案1】:

    您实际上是在实施 BFS(广度优先搜索)来检测从源 (S) 到目标 (D) 的路径是否存在。您只需在节点定义中维护一个父节点即可跟踪路径。

    将起始节点的父节点设置为空。然后,当您从 current 节点发现 BFS 中的节点时,将发现的节点的 parent 设置为 current 节点。

    现在,如果您的搜索成功(即您在搜索中点击了 D),只需从 D 向后遍历父节点链直到您点击 S,将访问过的父节点放入堆栈中。

    最后只是继续弹出堆栈直到它变空以获取从 S 到 D 路径上的节点。

    【讨论】:

    • A* 搜索(尤其是对于有很多障碍的大型矩阵来说更快)
    • 我必须想出一个更好的办法来返回从原点到目标的路径坐标。请看下面我的回答。我之前所做的对返回 int 值有好处,因此必须更改代码并对其进行处理。
    【解决方案2】:

    你得到的只是距离,因为你只返回源和目标之间的距离。 按照这些解决并打印路线;

    算法1:-

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

    算法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. 
    

    【讨论】:

    • 刚刚添加了我的完整答案,喜欢请点击
    【解决方案3】:
    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}
    

    【讨论】:

      猜你喜欢
      • 2015-05-28
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多