在 8×8 棋盤上放置 8 個皇後,使任意兩個皇後不同行、不同列、不同斜線。輸出所有合法擺放方案總數(經典結果為 92 種)。
設第 j 行皇後列位置為 x[j],第 k 行為 x[k]。衝突條件:
x[j] == x[k]|j - k| == |x[j] - x[k]|(行差等於列差)只要不滿足上述任一條件,即為合法位置。
public class EightQueensRecursive {
private int n = 8; // 皇後數/棋盤大小
private int sum = 0; // 解計數
private int[] x = new int[n + 1]; // 1-based 索引:x[i] 表示第 i 行皇后列號
public void solve(int row) {
if (row > n) { // 所有行已放置完畢,找到一個解
sum++;
printSolution();
return;
}
for (int col = 1; col <= n; col++) {
x[row] = col; // 嘗試在第 row 行第 col 列放置
if (isValid(row)) // 剪枝:檢查與前 row-1 行是否衝突
solve(row + 1);
}
}
private boolean isValid(int k) {
for (int j = 1; j < k; j++) {
if (x[j] == x[k] || Math.abs(j - k) == Math.abs(x[j] - x[k]))
return false;
}
return true;
}
private void printSolution() {
System.out.print("解 " + sum + ": ");
for (int i = 1; i <= n; i++) System.out.print(x[i] + " ");
System.out.println();
}
public static void main(String[] args) {
new EightQueensRecursive().solve(1);
System.out.println("總解數: " + new EightQueensRecursive().sum); // 輸出 92
}
}
public class EightQueensIterative {
private int n = 8;
private int sum = 0;
private int[] x = new int[n + 1]; // 1-based
public void solve() {
int row = 1; // 當前處理行
while (row >= 1) {
x[row]++; // 嘗試下一列
// 在當前行尋找合法列
while (x[row] <= n && !isValid(row)) {
x[row]++;
}
if (x[row] <= n) { // 找到合法列
if (row == n) { // 最後一行,得到一個解
sum++;
printSolution();
} else {
row++; // 轉入下一行
}
} else { // 當前行無合法列,回溯
x[row] = 0; // 重置當前行
row--; // 退回上一行
}
}
}
private boolean isValid(int k) {
for (int j = 1; j < k; j++) {
if (x[j] == x[k] || Math.abs(j - k) == Math.abs(x[j] - x[k]))
return false;
}
return true;
}
// printSolution 同遞歸版
}
| 維度 | 遞歸 DFS | 迭代回溯 |
|---|---|---|
| 代碼可讀性 | 高,符合人類直覺 | 中,需理解顯式狀態機 |
| 棧溢出風險 | 深度受限於 JVM 棧(N>1000 可能溢出) | 無風險,堆上模擬棧 |
| 性能 | 略高(方法調用開銷) | 略低(循環開銷),差異可忽略 |
| 調試便利性 | 調用棧清晰 | 需觀察變量狀態 |
n=8 改為參數,支持任意 N。