[英]find the shortest path between two points with obstacles
我需要在給定障礙的網格中找到兩點之間的最短路徑。
給定一個二維矩陣,其中一些元素用1填充,其余元素被填充。 這里X意味着你不能遍歷那個特定的點。 從單元格中,您可以向左,向右,向上或向下移動。 給定矩陣中的兩個點找到這些點之間的最短路徑。 這里S是起點,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;
}
如果從一個點到另一個點的成本是固定的,那么針對此類問題的最有效算法是BFS(廣度優先搜索) 。 如果成本是可變的但是肯定的那么你需要使用Dijkstra算法 ,如果有負成本的可能性, Bellman-Ford算法將是正確的選擇。
還有一件事,為了讓自己對這類問題感到滿意,一種方法是更多地解決這類問題。 您將在此站點中找到此類問題。
希望這可以幫助 -
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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.