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

时间:2020-04-17 07:03:03

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

我有一个2D矩阵。 给定2D矩阵,其中某些元素用“ 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;
    }
}

3 个答案:

答案 0 :(得分:1)

本质上,您正在实现BFS(广度优先搜索),以检测从源(S)到目标(D)的路径的存在。跟踪路径所需要做的只是在Node定义中维护一个父Node。

将起始节点的父级设置为null。然后,从 current 节点作为BFS中的发现节点,将发现的节点的 parent 设置为 current 节点。

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

最后只是不断弹出堆栈,直到堆栈变空为止,以获取从S到D的路径上的节点。

答案 1 :(得分:0)

得到的只是距离,因为您只返回了源和目标之间的距离。 遵循这些来解决并打印路线;

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

答案 2 :(得分:0)

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}
相关问题