我正在研究一个迷宫求解器。它在我的前2个迷宫中运行得非常快,但是,我的第三个迷宫需要永远。我应该可以在一分钟内,在合理的硬件上做到这一点。
解决方法需要花费大量时间在我的高端游戏装备上。
以下是相关的源代码
import java.awt.Point;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
/**
* Created by jphamlett on 6/16/17.
*/
public class main {
static class fileIO {
public static String readFile(String path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}
static class mazeNode {
private Point point;
private int dist;
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public int getDist() {
return dist;
}
public void setDist(int dist) {
this.dist = dist;
}
public mazeNode(Point point, int dist) {
setPoint(point);
setDist(dist);
}
}
static class Solver {
private String[] pathGrid;
private int[][] gridLength;
public void setPath(String path) {
try {
this.pathGrid = generatePath(fileIO.readFile(path, Charset.defaultCharset()));
} catch (IOException e) {
e.printStackTrace();
}
}
public Point findA() {
for (int row = 0; row < pathGrid.length; row++) {
int pos = pathGrid[row].indexOf("A");
if (pos != -1) {
return new Point(row, pos);
}
}
return null; // Something went wrong
}
public Point findB() {
for (int row = 0; row < pathGrid.length; row++) {
int pos = pathGrid[row].indexOf("B");
if (pos != -1) {
return new Point(row, pos);
}
}
return null; // Something went wrong
}
public Boolean canMove(char symbol) {
return symbol != '#';
}
public String[] generatePath(String path) {
return path.split("\n");
}
public String[] getPath() {
return this.pathGrid;
}
// Use BFS to solve the maze
public int[][] solve(int[][] gridLength, Point src, Point dest) {
if (src == null || dest == null) {
return null;
}
gridLength[src.x][src.y] = 0; // Distance to self is 0
Boolean visited[][] = new Boolean[gridLength.length][gridLength[0].length]; //Set all booleans to false
for (Boolean[] booleans : visited) {
Arrays.fill(booleans, Boolean.FALSE);
}
//System.out.println("Finished making visited array");
visited[src.x][src.y] = Boolean.TRUE;
Queue<mazeNode> queue = new LinkedList<>();
mazeNode initialNode = new mazeNode(src, 0);
queue.add(initialNode);
while (!queue.isEmpty()) {
mazeNode currentNode = queue.peek();
Point currentPoint = currentNode.getPoint();
//System.out.println("Point: " + currentPoint);
visited[currentPoint.x][currentPoint.y] = Boolean.TRUE;
if (currentPoint.equals(dest)) {
return gridLength;
}
queue.poll();
// Add adjacent valid cells
try {
if (canMove(pathGrid[currentPoint.x].charAt(currentPoint.y - 1)) && !visited[currentPoint.x][currentPoint.y - 1]) {
gridLength[currentPoint.x][currentPoint.y - 1] = currentNode.getDist() + 1;
queue.add(new mazeNode(new Point(currentPoint.x, currentPoint.y - 1), currentNode.getDist() + 1));
}
} catch (IndexOutOfBoundsException e) {
}
try {
if (canMove(pathGrid[currentPoint.x].charAt(currentPoint.y + 1)) && !visited[currentPoint.x][currentPoint.y + 1]) {
gridLength[currentPoint.x][currentPoint.y + 1] = currentNode.getDist() + 1;
queue.add(new mazeNode(new Point(currentPoint.x, currentPoint.y + 1), currentNode.getDist() + 1));
}
} catch (IndexOutOfBoundsException e) {
}
try {
if (canMove(pathGrid[currentPoint.x - 1].charAt(currentPoint.y)) && !visited[currentPoint.x - 1][currentPoint.y]) {
gridLength[currentPoint.x - 1][currentPoint.y] = currentNode.getDist() + 1;
queue.add(new mazeNode(new Point(currentPoint.x - 1, currentPoint.y), currentNode.getDist() + 1));
}
} catch (IndexOutOfBoundsException e) {
}
try {
if (canMove(pathGrid[currentPoint.x + 1].charAt(currentPoint.y)) && !visited[currentPoint.x + 1][currentPoint.y]) {
gridLength[currentPoint.x + 1][currentPoint.y] = currentNode.getDist() + 1;
queue.add(new mazeNode(new Point(currentPoint.x + 1, currentPoint.y), currentNode.getDist() + 1));
}
} catch (IndexOutOfBoundsException e) {
}
}
return null; // Cannot be reached
}
public Solver(String path) {
setPath(path);
}
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
Solver solver = new Solver("mazes/maze3.txt");
int[][] path = solver.solve(new int[solver.getPath().length][solver.getPath()[0].length()], solver.findA(), solver.findB());
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println(totalTime);
for (int[] i : path) {
for (int j : i) {
System.out.print(j + " ");
}
System.out.println();
}
endTime = System.currentTimeMillis();
totalTime = endTime - startTime;
System.out.println(totalTime);
}
}
这是maze2.txt
###############B#############################################
##.....########.#......................................#...##
##.###.#........####################################.#.#.#.##
##.###.#.#########..........#########.......########.#.#.#.##
##.#####...........########.#.......#.#####.########.#.#.#.##
##.########################.#.#####.#.#...#.########.#.#.#.##
##............................#####.#.##.##.########.#.#.#.##
##.###.############################.#.##.##.########.#.#.#.##
##.###.##...#...#...#...#...#.......#.##.##.########.#.#.#.##
##.###....#...#...#...#...#...#######.##.##.########.#.#.#.##
##.##################################.##.##.########.#.#.#.##
##.......................................##.########.#.#.#.##
###########################################.########.#.#.#.##
###...............................#########..........#.#.#.##
########################.###########################.#.#.#.##
#........................#...........................#.#.#.##
#.######################.#############################.#.#.##
#.#..........#.........................................#.#.##
#.#.########.#.#########################################.#.##
#.#........#.#.#.........................................#.##
#.##########.#.#.#########################################.##
#............#.#.##........................................##
##############.#.#############################.#####.########
#..............................................#####........#
########################A####################################
我附加了maze3,因为这里的格式化使它奇怪地移动。
答案 0 :(得分:0)
您的问题是visited
数组。
首先,一个小问题:visited
数组不应该是Boolean[][]
。只需将其设为boolean[][]
,它会自动初始化为所有false
值,这样也可以消除初始化循环。
现在,主要问题是visited
未标记为true
,直到您实际处理该点为止。这意味着将相同的点添加到队列很多次。
示例迷宫:
#####################
#...#...#...#...#...#
A.#1..#2..#3..#4..#5B
#...#...#...#...#...#
#####################
在这种情况下,点1
被添加两次到队列。最高点2
的每个点也将被添加两次。点2
将被添加4次,点3
8次,点4
16次,点5
32次。
如您所见,这是每个要处理的轮次 1 的指数数量的队列项目,每次多个路径相遇时都会加倍。
解决方案:将visited
重命名为queued
,并在将其添加到队列的同时标记点true
,从而防止添加同一点多次。
结果:迷宫3的代码在不到50毫秒内完成。
1)通过&#34; round&#34;我的意思是处理离开始(距离)更远一步的所有排队点。