【发布时间】:2018-07-22 00:38:15
【问题描述】:
我的 npuzzle 解决方案适用于 2x2,但使用 3x3 时会出现堆栈溢出错误。我无法弄清楚出了什么问题。我正在使用 DFS 检查是否有任何路径有解决方案。 算法, - 向左、向右、向上和向下移动棋子。 - 对于每个检查状态是否已被访问。 - 如果未访问标记已访问并检查它是否与目标状态匹配。 我认为堆栈应该能够容纳所有状态,应该只有 181400 个状态吧?
请帮忙!
public class PuzzleSolvable {
public static final int N = 3;
public static int[][] s2 = new int[][]{{8, 2, 1},
{-1, 4, 3},
{7, 6, 5}};
public static void main(String[] args) {
int[][] stage1 = new int[][]{ //needs 5 swaps
{1, 2, 3},
{4, 5, 6},
{7, 8, -1}
};
/*int[][] stage1 = new int[][]{{1, 2},
{4, -1}};
int[][] stage2 = new int[][]{{-1, 1},
{4, 2}};*/
Map<String, Boolean> map = new HashMap<>();
boolean solution = false;
for (int i = 0; i <= 181440; i = i + 3000) {
if (isSolvable(stage1, map, i)) {
solution = true;
break;
}
}
if (solution) {
System.out.println("Solution exists");
}else{
System.out.println("Solution does not exist");
}
}
static boolean isSolvable(int[][] s1, Map<String, Boolean> map, int depth) {
if (depth > 3000) {
return false;
}
depth++;
System.out.println(serializeArray(s1));
System.out.println(map.size());
if (map.get(serializeArray(s1)) != null) {
return false;
}
if (equals(s1, s2)) {
return true;
}
map.put(serializeArray(s1), true);
return isSolvable(move(s1, 0), map, depth) ||
isSolvable(move(s1, 1), map, depth) ||
isSolvable(move(s1, 2), map, depth) ||
isSolvable(move(s1, 3), map, depth);
}
static String serializeArray(int[][] arr) {
String s = "";
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
s = s + arr[i][j];
}
}
return s;
}
static boolean equals(int[][] s1, int[][] s2) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (s1[i][j] != s2[i][j]) {
return false;
}
}
}
return true;
}
static int[][] move(int[][] arr, int direction) {
int[][] array = new int[N][N];
int posx = 0, posy = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
array[i][j] = arr[i][j];
if (arr[i][j] == -1) {
posx = i;
posy = j;
}
}
}
switch (direction) {
case 0://right
if (posy < N - 1) {
System.out.println("Swap right");
swap(array, posx, posy, posx, posy + 1);
}
break;
case 1://left
if (posy > 0) {
System.out.println("Swap left");
swap(array, posx, posy, posx, posy - 1);
}
break;
case 2://up
if (posx > 0) {
System.out.println("Swap up");
swap(array, posx, posy, posx - 1, posy);
}
break;
case 3://down
if (posx < N - 1) {
System.out.println("Swap down");
swap(array, posx, posy, posx + 1, posy);
}
break;
}
return array;
}
static void swap(int[][] arr, int posx, int posy, int x, int y) {
int temp = arr[posx][posy];
arr[posx][posy] = arr[x][y];
arr[x][y] = temp;
}}
已编辑: 使用递归深度限制器实现的工作版本更新代码。
【问题讨论】:
-
为什么要使用 dfs ?我假设你想要最短的路径,所以使用 bfs。
-
@c0der 确定这是一个选项,我正在努力,但在这里我需要帮助来修复此代码。您是否建议 DFS 总是导致堆栈溢出错误?所以不要用了?
-
不,我不是与堆栈溢出有关,而是与算法的选择有关。
-
我看不出解决方案帖子如何正确。
depth > 3000在第二个for循环后返回 false -
堆栈将在 3000 处崩溃并重试。散列图有可渗透的状态,所以它不会再试一次。这些例子对我有用。
标签: java recursion stack-overflow depth-first-search sliding-tile-puzzle