回溯
- 從問題的某一種可能出發, 搜索從這種情況出發所能達到的所有可能, 當這一條路走到” 盡頭 “的時候, 再倒回出發點, 從另一個可能出發, 繼續搜索。這種不斷” 回溯 “尋找解的方法, 稱作” 回溯法 “。
- 回溯是一種算法思想,可以用遞歸實現。
- 通俗點講回溯就是一種試探,類似於窮舉,但回溯有“剪枝”功能,比如求和問題。給定7個數字,1 2 3 4 5 6 7求和等於7的組合,從小到大搜索,選擇1+2+3+4 =10>7,已經超過了7,之後的5 6 7就沒必要在繼續了,這就是一種搜索過程的優化。
八皇后問題
- 如何能夠在 8×8 的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?
- 爲了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。
算法
- 逐一嘗試當前皇后的擺放位置
- 如果當前皇后與前面任意皇后處於同一條橫行、縱行或斜線上,則跳過循環。
- 如果當前皇后沒有衝突,則確定擺放位置,並擺放下一位皇后
- 如果所有皇后擺放完畢,則算法結束。
代碼
class EightQueen {
int N;
int[] pos;
int[] result;
public EightQueen() {
this.N = 8;
this.pos = new int[this.N];
this.result = new int[this.N];
}
public void setQueen(int k) {
if (k == this.N) {
for (int i = 0; i < pos.length; i++) {
this.result[i] = this.pos[i];
}
return;
}
for (int j = 0; j < pos.length; j++) {
int i;
for (i = 0; i < k; i++) {
if (this.pos[i] == j || Math.abs(j - this.pos[i]) == Math.abs(i - k)) {
break;
}
}
if (i == k) {
this.pos[i] = j;
setQueen(k + 1);
}
}
}
public void showResult() {
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result.length; j++) {
System.out.print(this.result[i] == j ? "X " : "O ");
}
System.out.println();
}
}
public static void main(String[] args) {
EightQueen eQueen = new EightQueen();
eQueen.setQueen(0);
eQueen.showResult();
}
}
核心回溯函數
public void setQueen(int k) {
if (k == this.N) {
for (int i = 0; i < pos.length; i++) {
this.result[i] = this.pos[i];
}
return;
}
for (int j = 0; j < pos.length; j++) {
int i;
for (i = 0; i < k; i++) {
if (this.pos[i] == j || Math.abs(j - this.pos[i]) == Math.abs(i - k)) {
break;
}
}
if (i == k) {
this.pos[i] = j;
setQueen(k + 1);
}
}
}
重點理解
- 皇后在棋盤上的位置本來應該用二維矩陣表示,但是因爲每行只有一個皇后,所以可以用一維數組簡化代替。
- k既可以理解爲皇后的序號,也可以理解爲矩陣的row。
- 通常我們對數據(比如矩陣)做雙重循環時,習慣性的將外部for循環用於row的迭代,內部for循環用於col的迭代。因爲內部循環速度快於外部,於是我們就可以對數據進行從上到下,從左到右的操作。但在這個回溯函數中,我們的外部循環反相當於col迭代,這是因爲,對於每一個可能的位置,我們都要和前面所有已經就爲的皇后進行比對。
pos[i] == j
表示當我們將皇后k擺放在j位置時,很不幸皇后i也在j位置,所以列重複
Math.abs(k - i) == Math.abs(j - pos[i])
表示斜線重複,斜線有4個方向,45°角左上右上左下右下,剛好就是幾何方程∣x∣=∣y∣的樣子,進一步展開就是∣x1−x2∣=∣y1−y2∣
結果
O O O O O O O X
O O O X O O O O
X O O O O O O O
O O X O O O O O
O O O O O X O O
O X O O O O O O
O O O O O O X O
O O O O X O O O