八皇后问题描述
八皇后问题是国际象棋上的一个经典问题,要求在 (8 \times 8) 的棋盘上摆放 8 个皇后,使得它们不能互相攻击。根据国际象棋规则,皇后可以沿着行、列和对角线移动,因此问题的核心是如何保证每个皇后都不会在这些方向上攻击到其他皇后。
解题思路
八皇后问题通常使用**回溯算法(Backtracking)**进行求解,基本思路如下:
- 从第一行开始放置皇后,每行只能放一个皇后。
- 在当前行选择一个列位置放置皇后,然后进入下一行进行递归。
- 检查皇后是否被攻击:
- 同列是否已有皇后。
- 左上、右上两个对角线是否已有皇后。
- 如果在当前行找不到合适的位置,就回溯到上一行,尝试新的列位置。
- 当所有 8 个皇后都成功放置时,找到一个解,并继续寻找下一个解。
Java 代码实现
以下是 Java 语言实现的回溯法求解八皇后问题的代码:
import java.util.ArrayList;
import java.util.List;
public class EightQueens {
private static final int SIZE = 8; // 棋盘大小
private int[] queens = new int[SIZE]; // 记录每行皇后所在的列
private List<List<String>> solutions = new ArrayList<>();
public static void main(String[] args) {
EightQueens solver = new EightQueens();
solver.solve(0);
solver.printSolutions();
}
// 递归尝试在 row 行放置皇后
private void solve(int row) {
if (row == SIZE) {
saveSolution(); // 找到一个解
return;
}
for (int col = 0; col < SIZE; col++) {
if (isSafe(row, col)) { // 检查当前位置是否安全
queens[row] = col; // 放置皇后
solve(row + 1); // 递归到下一行
}
}
}
// 检查皇后放置是否合法
private boolean isSafe(int row, int col) {
for (int i = 0; i < row; i++) {
if (queens[i] == col || // 检查列冲突
Math.abs(queens[i] - col) == Math.abs(i - row)) { // 检查对角线冲突
return false;
}
}
return true;
}
// 保存当前解法
private void saveSolution() {
List<String> board = new ArrayList<>();
for (int i = 0; i < SIZE; i++) {
char[] row = new char[SIZE];
for (int j = 0; j < SIZE; j++) {
row[j] = (queens[i] == j) ? 'Q' : '.';
}
board.add(new String(row));
}
solutions.add(board);
}
// 打印所有解
private void printSolutions() {
int count = 1;
for (List<String> solution : solutions) {
System.out.println("解法 " + count + ":");
for (String row : solution) {
System.out.println(row);
}
System.out.println();
count++;
}
System.out.println("共找到 " + solutions.size() + " 种解法。");
}
}
代码解析
-
solve(int row)
- 递归地尝试在
row
行放置皇后。 - 遍历当前行的每一列,检查是否可以放置皇后。
- 若可以放置,记录皇后位置,并递归到下一行。
- 递归地尝试在
-
isSafe(int row, int col)
- 遍历之前的
row
行,检查col
是否已经有皇后,或者是否在对角线上。
- 遍历之前的
-
saveSolution()
- 将当前成功放置的皇后棋盘保存成字符串列表,以便打印所有解法。
-
printSolutions()
- 遍历
solutions
,输出所有可行的棋盘布局。
- 遍历
运行结果示例
运行代码后,将输出所有 92 种合法解法(由于解法较多,这里仅展示部分):
解法 1:
Q.......
...Q....
.....Q..
.......Q
..Q.....
......Q.
.Q......
....Q...
解法 2:
Q.......
....Q...
......Q.
.Q......
.......Q
..Q.....
.....Q..
...Q....
...
共找到 92 种解法。
时间复杂度分析
- 由于每行最多只能放一个皇后,搜索空间减少到 O(N!),即 O(8!) = 40,320,虽然指数级增长,但对于 8 皇后问题可以接受。
- 由于剪枝(提前检查列、对角线),实际搜索的状态数远小于 O(N!)。