Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 找到有障碍物的两点之间的最短路径_Java_Algorithm_Data Structures_Breadth First Search - Fatal编程技术网

Java 找到有障碍物的两点之间的最短路径

Java 找到有障碍物的两点之间的最短路径,java,algorithm,data-structures,breadth-first-search,Java,Algorithm,Data Structures,Breadth First Search,我需要在给定障碍物的网格中找到两点之间的最短路径 给定一个二维矩阵,其中一些元素被填充 用1填充,其余元素将被填充。这里X表示你不能 遍历到那个特定的点。从一个细胞你可以 向左、向右、向上或向下移动。给定矩阵中的两点 找到这些点之间的最短路径。这是开始 点,E是终点 我提出了下面的代码,但我想从访谈的角度了解解决这个问题最有效的算法是什么?有没有更好的办法 public static void main(String[] args) { char[][] matrix = {{'1

我需要在给定障碍物的网格中找到两点之间的最短路径

给定一个二维矩阵,其中一些元素被填充 用1填充,其余元素将被填充。这里X表示你不能 遍历到那个特定的点。从一个细胞你可以 向左、向右、向上或向下移动。给定矩阵中的两点 找到这些点之间的最短路径。这是开始 点,E是终点

我提出了下面的代码,但我想从访谈的角度了解解决这个问题最有效的算法是什么?有没有更好的办法

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

    System.out.println(shortestPath(matrix));
  }

  public static int shortestPath(char[][] matrix) {
    int s_row = 0, s_col = 0;
    boolean flag = false;
    for (s_row = 0; s_row < matrix.length; s_row++) {
      for (s_col = 0; s_col < matrix[0].length; s_col++) {
        if (matrix[s_row][s_col] == 'S')
          flag = true;
        if (flag)
          break;
      }
      if (flag)
        break;
    }
    return shortestPath(matrix, s_row, s_col);
  }

  public static int shortestPath(char[][] matrix, int s_row, int s_col) {
    int count = 0;
    Queue<int[]> nextToVisit = new LinkedList<>();
    nextToVisit.offer(new int[] {s_row, s_col});
    Set<int[]> visited = new HashSet<>();
    Queue<int[]> temp = new LinkedList<>();

    while (!nextToVisit.isEmpty()) {
      int[] position = nextToVisit.poll();
      int row = position[0];
      int col = position[1];

      if (matrix[row][col] == 'E')
        return count;
      if (row > 0 && !visited.contains(new int[] {row - 1, col}) && matrix[row - 1][col] != 'X')
        temp.offer(new int[] {row - 1, col});
      if (row < matrix.length - 1 && !visited.contains(new int[] {row + 1, col})
          && matrix[row + 1][col] != 'X')
        temp.offer(new int[] {row + 1, col});
      if (col > 0 && !visited.contains(new int[] {row, col - 1}) && matrix[row][col - 1] != 'X')
        temp.offer(new int[] {row, col - 1});
      if (col < matrix[0].length - 1 && !visited.contains(new int[] {row, col + 1})
          && matrix[row][col + 1] != 'X')
        temp.offer(new int[] {row, col + 1});

      if (nextToVisit.isEmpty() && !temp.isEmpty()) {
        nextToVisit = temp;
        temp = new LinkedList<>();
        count++;
      }

    }
    return count;
  }

对于这类问题,最有效的算法是如果从一个点到另一个点的成本是固定的。如果成本是可变的,但为正,那么您需要使用,如果存在负成本的可能性,则将是正确的选择


还有一件事,为了让自己适应这类问题,一种方法是更多地解决这类问题。您将在站点中找到此类问题。

解决此类问题的最有效算法是,如果从一个点到另一个点的成本是固定的。如果成本是可变的,但为正,那么您需要使用,如果存在负成本的可能性,则将是正确的选择

还有一件事,为了让自己适应这类问题,一种方法是更多地解决这类问题。您将在站点中发现此类问题。

希望这有帮助-

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import GridNavigationTest.Direction;

public class GridNavigationTest {
    public static final int[][] navigableGrid = new int[][] { 
        { 1, 1, 1, 1 }, 
        { 1, 0, 0, 1 }, 
        { 1, 0, 1, 1 },
        { 1, 0, 1, 0 }, 
        { 1, 1, 9, 0 }
    };

    public enum Direction {
        UP, DOWN, RIGHT, LEFT;

        public Direction reverse() {
            Direction reverse = null;

            if (this.equals(Direction.UP)) {
                reverse = DOWN;
            } else if (this.equals(Direction.DOWN)) {
                reverse = UP;
            } else if (this.equals(Direction.RIGHT)) {
                reverse = LEFT;
            } else if (this.equals(Direction.LEFT)) {
                reverse = RIGHT;
            }

            return reverse;
        }
    };

    private static final Map<String, PathNode> nodesRegistry = new TreeMap<>();
    private static final RouteRegistry routeRegistry = new RouteRegistry();

    private static final String keyRefDelimiter = ":";
    private static final String keyRefFormat = "%d" + keyRefDelimiter + "%d";

    private static PathNode destinationNode = null;

    public static void main(String... arguments) {
        createNodesRegistry();
        findRoutes();
        printSignificantRoutes();
    }

    private static void printSignificantRoutes() {
        String shortestRoute = Arrays.toString(routeRegistry.getShortestRoute());
        System.out.println("-> Shortest\t: " + shortestRoute);

        String longestRoute = Arrays.toString(routeRegistry.getLongestRoute());
        System.out.println("-> Longest\t: " + longestRoute);
    }

    private static void createNodesRegistry() {
        for (int rowCount = 0; rowCount < navigableGrid.length; rowCount++) {
            for (int colCount = 0; colCount < navigableGrid[rowCount].length; colCount++) {
                // add current element's node representation to the nodes map, only if it is
                // active (value > 0)
                if (navigableGrid[rowCount][colCount] > 0) {
                    IntPair point = new IntPair(rowCount, colCount);
                    int value = navigableGrid[rowCount][colCount];

                    PathNode currentElementNode = new PathNode(point, value);
                    nodesRegistry.put(String.format(keyRefFormat, rowCount, colCount), currentElementNode);

                    // set adjacent references
                    setAdjacentReference(currentElementNode, rowCount - 1, colCount, Direction.UP);
                    setAdjacentReference(currentElementNode, rowCount + 1, colCount, Direction.DOWN);
                    setAdjacentReference(currentElementNode, rowCount, colCount + 1, Direction.RIGHT);
                    setAdjacentReference(currentElementNode, rowCount, colCount - 1, Direction.LEFT);

                    if (currentElementNode.getNodeValue() == 9) {
                        destinationNode = currentElementNode;
                    }
                }
            }
        }
    }

    private static void setAdjacentReference(PathNode currentNode, int row, int col, Direction direction) {
        PathNode adjacentNode = nodesRegistry.get(String.format(keyRefFormat, row, col));
        if (adjacentNode != null) {
            currentNode.setAdjacentNode(direction, adjacentNode);

            // set the reverse lookup link
            if (adjacentNode.getAdjacentNode(direction.reverse()) == null) {
                adjacentNode.setAdjacentNode(direction.reverse(), currentNode);
            }
        }
    }

    private static void findRoutes() {
        // initialize reverse tracing from the destination
        destinationNode.traceRoute(routeRegistry, null);
    }
}

class PathNode {
    private int nodeValue = 0;
    private Map<Direction, PathNode> adjacentNodes = new HashMap<>();
    private IntPair location = null;

    public PathNode() {
        super();
    }

    public PathNode(IntPair location, int value) {
        super();
        this.location = location;
        this.nodeValue = value;
    }

    public void traceRoute(RouteRegistry routeRegistry, PathNode fromNode) {
        if (!this.isStartNode()) {
            for (Entry<Direction, PathNode> entry : this.adjacentNodes.entrySet()) {
                PathNode node = entry.getValue(); 
                if (!node.equals(fromNode)) {
                    routeRegistry.put(this.location);
                    node.traceRoute(routeRegistry, this);
                }
            }
        } else {
            routeRegistry.put(this.location);
        }
    }

    public int getNodeValue() {
        return this.nodeValue;
    }

    public void setNodeValue(int value) {
        this.nodeValue = value;
    }

    public void setAdjacentNode(Direction direction, PathNode node) {
        this.adjacentNodes.put(direction, node);
    }

    public PathNode getAdjacentNode(Direction direction) {
        return this.adjacentNodes.get(direction);
    }

    public IntPair getLocation() {
        return location;
    }

    public void setLocation(IntPair location) {
        this.location = location;
    }

    public boolean isStartNode() {
        boolean returnValue = false;

        if (location != null) {
            returnValue = (location.getValue(0) == 0 && location.getValue(1) == 0);
        }

        return returnValue;
    }

    public boolean isDestinationNode() {
        return (this.getNodeValue() == 9);
    }
}

class IntPair {
    private Integer[] values = new Integer[2];

    public IntPair() {
        super();
    }

    public IntPair(Integer value1, Integer value2) {
        super();
        this.values[0] = value1;
        this.values[1] = value2;
    }

    public Integer getValue(int index) {
        return this.values[index];
    }

    public void setValue(int index, int value) {
        this.values[index] = value;
    }

    @Override
    public String toString() {
        return "[" + this.values[0] + ", " + this.values[1] + "]";
    }
}

class RouteRegistry {
    private int routeIndex = 1;
    private Map <String, List<IntPair>> routesMap = new HashMap<>();

    public RouteRegistry() {
        super();
    }

    public void put(IntPair point) {
        String activeRouteKey = String.format("Route %d", routeIndex);
        routesMap.computeIfAbsent(activeRouteKey, k -> new ArrayList<IntPair>());

        List<IntPair> routePoints = routesMap.get(activeRouteKey);
        routePoints.add(point);

        if (point.getValue(0) == 0 && point.getValue(1) == 0) {
            routeIndex++;
        }
    }

    public IntPair[] getShortestRoute() {
        IntPair[] routeArray = null;

        List<IntPair> shortestRoute = null;
        for (Entry<String, List<IntPair>> routeEntry :  routesMap.entrySet()) {
            List<IntPair> route = routeEntry.getValue();

            if (shortestRoute == null || shortestRoute.size() > route.size()) {
                shortestRoute = route;
            }
        }

        if (shortestRoute != null) {
            routeArray = shortestRoute.toArray(new IntPair[shortestRoute.size()]);
        } else {
            routeArray = new IntPair[0];
        }

        return routeArray;
    }

    public IntPair[] getLongestRoute() {
        IntPair[] routeArray = null;

        List<IntPair> longestRoute = null;
        for (Entry<String, List<IntPair>> routeEntry :  routesMap.entrySet()) {
            List<IntPair> route = routeEntry.getValue();

            if (longestRoute == null || longestRoute.size() < route.size()) {
                longestRoute = route;
            }
        }

        if (longestRoute != null) {
            routeArray = longestRoute.toArray(new IntPair[longestRoute.size()]);
        } else {
            routeArray = new IntPair[0];
        }

        return routeArray;
    }
}
希望这有帮助-

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import GridNavigationTest.Direction;

public class GridNavigationTest {
    public static final int[][] navigableGrid = new int[][] { 
        { 1, 1, 1, 1 }, 
        { 1, 0, 0, 1 }, 
        { 1, 0, 1, 1 },
        { 1, 0, 1, 0 }, 
        { 1, 1, 9, 0 }
    };

    public enum Direction {
        UP, DOWN, RIGHT, LEFT;

        public Direction reverse() {
            Direction reverse = null;

            if (this.equals(Direction.UP)) {
                reverse = DOWN;
            } else if (this.equals(Direction.DOWN)) {
                reverse = UP;
            } else if (this.equals(Direction.RIGHT)) {
                reverse = LEFT;
            } else if (this.equals(Direction.LEFT)) {
                reverse = RIGHT;
            }

            return reverse;
        }
    };

    private static final Map<String, PathNode> nodesRegistry = new TreeMap<>();
    private static final RouteRegistry routeRegistry = new RouteRegistry();

    private static final String keyRefDelimiter = ":";
    private static final String keyRefFormat = "%d" + keyRefDelimiter + "%d";

    private static PathNode destinationNode = null;

    public static void main(String... arguments) {
        createNodesRegistry();
        findRoutes();
        printSignificantRoutes();
    }

    private static void printSignificantRoutes() {
        String shortestRoute = Arrays.toString(routeRegistry.getShortestRoute());
        System.out.println("-> Shortest\t: " + shortestRoute);

        String longestRoute = Arrays.toString(routeRegistry.getLongestRoute());
        System.out.println("-> Longest\t: " + longestRoute);
    }

    private static void createNodesRegistry() {
        for (int rowCount = 0; rowCount < navigableGrid.length; rowCount++) {
            for (int colCount = 0; colCount < navigableGrid[rowCount].length; colCount++) {
                // add current element's node representation to the nodes map, only if it is
                // active (value > 0)
                if (navigableGrid[rowCount][colCount] > 0) {
                    IntPair point = new IntPair(rowCount, colCount);
                    int value = navigableGrid[rowCount][colCount];

                    PathNode currentElementNode = new PathNode(point, value);
                    nodesRegistry.put(String.format(keyRefFormat, rowCount, colCount), currentElementNode);

                    // set adjacent references
                    setAdjacentReference(currentElementNode, rowCount - 1, colCount, Direction.UP);
                    setAdjacentReference(currentElementNode, rowCount + 1, colCount, Direction.DOWN);
                    setAdjacentReference(currentElementNode, rowCount, colCount + 1, Direction.RIGHT);
                    setAdjacentReference(currentElementNode, rowCount, colCount - 1, Direction.LEFT);

                    if (currentElementNode.getNodeValue() == 9) {
                        destinationNode = currentElementNode;
                    }
                }
            }
        }
    }

    private static void setAdjacentReference(PathNode currentNode, int row, int col, Direction direction) {
        PathNode adjacentNode = nodesRegistry.get(String.format(keyRefFormat, row, col));
        if (adjacentNode != null) {
            currentNode.setAdjacentNode(direction, adjacentNode);

            // set the reverse lookup link
            if (adjacentNode.getAdjacentNode(direction.reverse()) == null) {
                adjacentNode.setAdjacentNode(direction.reverse(), currentNode);
            }
        }
    }

    private static void findRoutes() {
        // initialize reverse tracing from the destination
        destinationNode.traceRoute(routeRegistry, null);
    }
}

class PathNode {
    private int nodeValue = 0;
    private Map<Direction, PathNode> adjacentNodes = new HashMap<>();
    private IntPair location = null;

    public PathNode() {
        super();
    }

    public PathNode(IntPair location, int value) {
        super();
        this.location = location;
        this.nodeValue = value;
    }

    public void traceRoute(RouteRegistry routeRegistry, PathNode fromNode) {
        if (!this.isStartNode()) {
            for (Entry<Direction, PathNode> entry : this.adjacentNodes.entrySet()) {
                PathNode node = entry.getValue(); 
                if (!node.equals(fromNode)) {
                    routeRegistry.put(this.location);
                    node.traceRoute(routeRegistry, this);
                }
            }
        } else {
            routeRegistry.put(this.location);
        }
    }

    public int getNodeValue() {
        return this.nodeValue;
    }

    public void setNodeValue(int value) {
        this.nodeValue = value;
    }

    public void setAdjacentNode(Direction direction, PathNode node) {
        this.adjacentNodes.put(direction, node);
    }

    public PathNode getAdjacentNode(Direction direction) {
        return this.adjacentNodes.get(direction);
    }

    public IntPair getLocation() {
        return location;
    }

    public void setLocation(IntPair location) {
        this.location = location;
    }

    public boolean isStartNode() {
        boolean returnValue = false;

        if (location != null) {
            returnValue = (location.getValue(0) == 0 && location.getValue(1) == 0);
        }

        return returnValue;
    }

    public boolean isDestinationNode() {
        return (this.getNodeValue() == 9);
    }
}

class IntPair {
    private Integer[] values = new Integer[2];

    public IntPair() {
        super();
    }

    public IntPair(Integer value1, Integer value2) {
        super();
        this.values[0] = value1;
        this.values[1] = value2;
    }

    public Integer getValue(int index) {
        return this.values[index];
    }

    public void setValue(int index, int value) {
        this.values[index] = value;
    }

    @Override
    public String toString() {
        return "[" + this.values[0] + ", " + this.values[1] + "]";
    }
}

class RouteRegistry {
    private int routeIndex = 1;
    private Map <String, List<IntPair>> routesMap = new HashMap<>();

    public RouteRegistry() {
        super();
    }

    public void put(IntPair point) {
        String activeRouteKey = String.format("Route %d", routeIndex);
        routesMap.computeIfAbsent(activeRouteKey, k -> new ArrayList<IntPair>());

        List<IntPair> routePoints = routesMap.get(activeRouteKey);
        routePoints.add(point);

        if (point.getValue(0) == 0 && point.getValue(1) == 0) {
            routeIndex++;
        }
    }

    public IntPair[] getShortestRoute() {
        IntPair[] routeArray = null;

        List<IntPair> shortestRoute = null;
        for (Entry<String, List<IntPair>> routeEntry :  routesMap.entrySet()) {
            List<IntPair> route = routeEntry.getValue();

            if (shortestRoute == null || shortestRoute.size() > route.size()) {
                shortestRoute = route;
            }
        }

        if (shortestRoute != null) {
            routeArray = shortestRoute.toArray(new IntPair[shortestRoute.size()]);
        } else {
            routeArray = new IntPair[0];
        }

        return routeArray;
    }

    public IntPair[] getLongestRoute() {
        IntPair[] routeArray = null;

        List<IntPair> longestRoute = null;
        for (Entry<String, List<IntPair>> routeEntry :  routesMap.entrySet()) {
            List<IntPair> route = routeEntry.getValue();

            if (longestRoute == null || longestRoute.size() < route.size()) {
                longestRoute = route;
            }
        }

        if (longestRoute != null) {
            routeArray = longestRoute.toArray(new IntPair[longestRoute.size()]);
        } else {
            routeArray = new IntPair[0];
        }

        return routeArray;
    }
}

原则上这很好,看起来很像BFS,对吧?。您可以做一些优化:尽量避免频繁分配新内存,将访问标志存储在固定大小的列表中,而不是散列集中。有关更详细的回顾,请访问。请参阅答案。这在原则上很好,看起来很像BFS,对吗?。您可以做一些优化:尽量避免频繁分配新内存,将访问标志存储在固定大小的列表中,而不是散列集中。有关更详细的回顾,请转至。请参阅答案。虽然这可能是解决方案,但最好以某种方式解释您的方法以及它如何优于OPs源代码。此实现基本上创建了矩阵中所有节点的图形,以及它们与相邻节点的关系。此后,从目标实现BFS,直到-[1]递归的起点或[2]结束。最后,它识别最短和最长路径条目,并打印相同的条目。虽然这可能是解决方案,但最好以某种方式解释您的方法,以及它如何优于OPs源代码。此实现基本上从矩阵创建所有节点的图,以及它们与相邻节点的关系。此后,从目标实现BFS,直到-[1]递归的起点或[2]结束。最后,它识别最短和最长路径条目,并打印相同的条目。