我试图让Java程序找到迷宫中的最短路径并打印出路的长度。
。是一种方式和' x'是障碍。
如果我输入
....xxx.
x.x....x
xxx.....
x......x
...xxxxx
........
xxx.....
xx......
输出是无限的:
0, 0
0, 1
1, 1
0, 1
1, 1
0, 1
1, 1
0, 1
1, 1
0, 1
1, 1
0, 1
1, 1
0, 1
...
发生了和java.lang.StackOverflowError。
正确的输出必须是
0, 0
0, 1
1, 1
0, 1
0, 2
0, 3
1, 3
2, 3
3, 3
3, 4
3, 5
3, 6
3, 5
3, 4
3, 3
3. 2
4, 2
5, 2
5, 3
6, 3
7, 3
7, 4
7, 5
7, 6
7, 7
16
如何修改代码并获得正确答案? 或者我应该使用什么算法来制作新代码? 我很困惑..
我尝试了很多次但是我无法得到正确答案T_T Plz帮帮我
import java.util.Scanner;
public class ShortestMazeWay
{
static int count=0;
static int[] result = new int[10000]; // save the move direction
static int[][] find = new int[8][8];
static int[][] maze = new int[8][8]; // 0 = can go, 1 = can not go
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
for(int i=0; i<8; i++)
{
String str = sc.nextLine();
for(int j=0; j<8; j++)
{
if(str.charAt(j)=='.')
maze[i][j]=0;
else
maze[i][j]=1;
}
}
find(0, 0); // start from (0, 0)
}
static void find(int i, int j)
{
find[i][j] = 1; // 0 = can go, 1 = can not go
System.out.println(i+", "+j); // to check the way
if(i==7 && j==7) // the end point is (7, 7)
System.out.println(count);
else
{
count++;
if(i+1<8 && maze[i+1][j]!=1 && find[i+1][j]==0) // ↓
{
result[count] = 1;
find[i][j] = 0;
find(i+1, j);
}
else if(j+1<8 && maze[i][j+1]!=1 && find[i][j+1]==0) // →
{
result[count] = 2;
find[i][j] = 0;
find(i, j+1);
}
else if(i-1>=0 && maze[i-1][j]!=1 && find[i-1][j]==0) // ↑
{
if(result[count-1]==2) // if moved ↓ in previous step,
count--; // go back to previous position
else
result[count] = 3;
find[i][j] = 0;
find(i-1, j);
}
else if(j-1>=0 && maze[i][j-1]!=1 && find[i][j-1]==0) // ←
{
if(result[count-1]==1) // if moved → in previous step,
count--; // go back to previous position
else
result[count] = 4;
find[i][j] = 0;
find(i, j-1);
}
}
}
}
答案 0 :(得分:5)
走在.
时,您需要确保不要踩到已经踩过的.
。
这样做的一种方法是留下面包屑,例如:将.
更改为*
,并记住将其更改回&#39;。&#39;当你回溯时。
示例:方向顺序为up
,right
,down
,left
:
*...xxx. 1 **..xxx. 2 ***.xxx. 3 ****xxx. 4 ****xxx. 5 ****xxx. 6
x.x....x x.x....x x.x....x x.x....x x.x*...x x.x**..x
xxx..... xxx..... xxx..... xxx..... xxx..... xxx.....
x......x x......x x......x x......x x......x x......x
...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx
........ ........ ........ ........ ........ ........
xxx..... xxx..... xxx..... xxx..... xxx..... xxx.....
xx...... xx...... xx...... xx...... xx...... xx......
****xxx. 7 ****xxx. 8 ****xxx. 9 ****xxx. 10 ****xxx. 11 ****xxx. 12
x.x***.x x.x****x x.x****x x.x****x x.x****x x.x****x
xxx..... xxx..... xxx...*. xxx...** xxx...*. xxx...*.
x......x x......x x......x x......x x.....*x x....**x
...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx
........ ........ ........ ........ ........ ........
xxx..... xxx..... xxx..... xxx..... xxx..... xxx.....
xx...... xx...... xx...... xx...... xx...... xx......
****xxx. 13 ****xxx. 14 ****xxx. 15 ****xxx. 16 ****xxx. 17 ****xxx. 18
x.x****x x.x****x x.x****x x.x****x x.x****x x.x****x
xxx..**. xxx.***. xxx.***. xxx.***. xxx****. xxx.***.
x....**x x....**x x...***x x..****x x..****x x.*****x
...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx ...xxxxx
........ ........ ........ ........ ........ ........
xxx..... xxx..... xxx..... xxx..... xxx..... xxx.....
xx...... xx...... xx...... xx...... xx...... xx......
注意它在第10步和第11步之间以及第17步和第18步之间的回溯。
记住:第一次走到尽头不一定是最短的路线。您必须尝试所有步骤的所有组合,并记住找到的最短路径,而不仅仅是找到的第一条路径。
使用上面使用的方向顺序,以下是完整路线的一些示例:
First Shortest Shortest Last Longest
****xxx. ****xxx. ****xxx. ****xxx. ****xxx.
x.x****x x.x*...x x.x*...x x.x*...x x.x****x
xxx.***. xxx*.... xxx*.... xxx*.... xxx.***.
x.*****x x.**...x x.**...x x***...x x.*****x
..*xxxxx ..*xxxxx ..*xxxxx **.xxxxx ***xxxxx
..****** ..****** ..***... ****.... ********
xxx....* xxx....* xxx.***. xxx*.... xxx*****
xx.....* xx.....* xx....** xx.***** xx.*****
因此,因为你必须记住每次结束时所采用的完整路由,所以堆栈实现优于当前使用的递归实现。
更新:优化
在没有回溯的情况下重新思考解决问题的方法,这意味着它应该更快。
使用步骤编号替换面包屑,即到达该位置的(最少)步数。
初始化maze
,-1
被屏蔽(x
),Integer.MAX_VALUE
被开放(.
),然后执行此操作:
walk(maze, 0, 0, 1);
private static void walk(int[][] maze, int y, int x, int step) {
if (y >= 0 && y < 8 && x >= 0 && x < 8 && maze[y][x] > step) {
maze[y][x] = step;
walk(maze, y - 1, x, step + 1);
walk(maze, y + 1, x, step + 1);
walk(maze, y, x + 1, step + 1);
walk(maze, y, x - 1, step + 1);
}
}
结果是这样的迷宫:
1 2 3 4 XX XX XX .. <-- Unreachable
XX 3 XX 5 6 7 8 XX
XX XX XX 6 7 8 9 10
XX 9 8 7 8 9 10 XX
11 10 9 XX XX XX XX XX
12 11 10 11 12 13 14 15
XX XX XX 12 13 14 15 16
XX XX 14 13 14 15 16 17
现在,您可以通过跟踪结尾(17
)找到最短路径,转到较低的数字,直到您回到开头(1
)。