8皇后非攻击问题代码仅重复输出首个解决方案,求排查修复
问题原因与修复方案
问题原因
你的代码核心问题是搜索逻辑错误:
- 原
solve()方法遍历整个棋盘的所有位置尝试放置皇后,而非按行递进放置。这种方式会导致回溯后,程序反复从棋盘起始位置重新构建出第一个找到的解,直到solutionCount达到92,因此重复打印同一个方案。 - 每次递归都遍历整个棋盘统计皇后数量,不仅效率低下,还无法引导搜索路径向不同解推进,只能在同一个解的构建路径上循环。
修复方案
采用按行递归的策略,每行仅尝试放置一个皇后,系统遍历所有列的组合,确保找到所有不同解。具体修改如下:
1. 重构solve()方法,添加按行处理的辅助方法
将原无参solve()改为调用带行号参数的私有辅助方法,按行递进处理:
public void solve() { solve(0); // 从第0行开始放置皇后 } // 私有辅助方法:处理第row行的皇后放置 private void solve(int row) { // 已找到全部92个解,终止递归 if (solutionCount == 92) { return; } // 所有行都完成皇后放置,找到一个解 if (row == 8) { solutionCount++; System.out.println("Solution " + solutionCount + ":"); print(); return; } // 在当前行的每一列尝试放置皇后 for (int col = 0; col < 8; col++) { if (canPlace(row, col)) { board[row][col] = 1; solve(row + 1); // 递归处理下一行 board[row][col] = 0; // 回溯:移除当前皇后,尝试下一列 } } }
2. 优化canPlace()方法(可选但推荐)
由于按行放置时,当前行还未放置皇后,因此可以去掉冗余的行检查,只需要检查当前列及上方的对角线,提升效率:
public boolean canPlace(int x, int y) { // 检查当前列上方是否有皇后 for (int i = 0; i < x; i++) { if (board[i][y] == 1) { return false; } } // 检查左上到右下的对角线(仅上方行) for (int i = x - 1, j = y - 1; i >= 0 && j >= 0; i--, j--) { if (board[i][j] == 1) { return false; } } // 检查右上到左下的对角线(仅上方行) for (int i = x - 1, j = y + 1; i >= 0 && j < 8; i--, j++) { if (board[i][j] == 1) { return false; } } return true; }
修复效果
修改后,程序会按行系统遍历所有可能的列组合,正确找到8皇后问题的全部92个不同解,每个解仅打印一次。
内容的提问来源于stack exchange,提问作者doug
相关产品推荐
相关产品推荐

