回溯的描述:
回溯算法將解空間看作一定的結構,通常為樹形結構,一個解對應於樹中的一片樹葉。算法從樹根(即初始狀態出發),嘗試所有可能到達的結點。當不能前行時就后退一步或若干步,再從另一個結點開始繼續搜索,直到嘗試完所有的結點。也可以用走迷宮的方式去理解回溯,設想把你放在一個迷宮里,想要走出迷宮,最直接的辦法是什么呢?沒錯,試。先選一條路走起,走不通就往回退嘗試別的路,走不通繼續往回退,直到走遍所有的路,並且在走的過程中你可以記錄所有能走出迷宮的路線。
回溯與八皇后問題
在國際象棋中,皇后是最強大的一枚棋子,可以吃掉與其在同一行、列和斜線的敵方棋子。八皇后問題是這樣一個問題:將八個皇后擺在一張8*8的國際象棋棋盤上,使每個皇后都無法吃掉別的皇后,一共有多少種擺法?
如果使用暴力算法的話要在8*8個格子中選擇8個格子來擺放皇后,一共要嘗試C864次,十億級別的嘗試次數!
稍加分析,我們可以得到一個不那么暴力的辦法,顯然,每行每列最多只能有一個皇后,如果基於這個事實進行暴力破解,那結果會好得多。安排皇后時,第一行有8種選法,一旦第一行選定,假設選為(1,i),第二行只能選(2,j),其中j!=i,所以有7種選法。以此類推,需要窮舉的情況有8!=40320種。
我們先降下規模來看看4皇后問題:4個皇后在4*4的格子里各自安排不打架,一共有多少種安排方法?
試着來窮舉一下,真的需要4!=24次嘗試嗎?現在我們把第一個皇后放在第一個格子,被塗黑的地方是不能放皇后的。
第二行的皇后只能放在第三格或第四格,按照回溯我們要先嘗試放在第三格,則:
這樣第三位皇后無論放哪里都難逃被吃掉的厄運。於是在第一個皇后位於1號,第二個皇后位於3號的情況下問題無解。我們只能返回上一步來,給2號皇后換個位置。
顯然,第三個皇后只有一個位置可選。當第三個皇后占據第三行藍色空位時,第四行皇后無路可走,於是發生錯誤,返回上層調用(3號皇后),而3號也別無可去,繼續返回上層調用(2號),2號已然無路可去,繼續返回上層(1號),於是1號皇后改變位置如下,繼續搜索。
話說到這里,我們對“回溯法”已經有了基本概念。然而所謂知易行難,理解算法和將算法寫出來完全是兩回事。下面來看看代碼:
代碼不長,注釋很多
#include <iostream> using namespace std; bool isOk(int c[], int row, int n); //函數:判斷能否在第row行第c[row]列插入一個皇后 void queen(int row, int c[], int n, int& total); //函數:回溯的核心部分 int main() { int n; //皇后的數量 cout << "Please enter the number of queen:\n"; cin >> n; int* c = new int[n]; //記錄皇后的位置,例如c[i]的值為j表示第i行的皇后放在第j列 int total = 0; //解決方案的種數 queen(0, c, n, total); cout << "The number of solution is:\n" << total; return 0; } void queen(int row, int c[], int n, int& total) { if (row == n) //當row等於n的時候表示皇后全部擺放完畢 { for (int i = 0; i < n; i++) cout << c[i] << " "; cout << endl; total++; } else //皇后還未擺放完,則執行下面程序 { //遍歷所有的列,看看第row行皇后可以放在第幾列 for (int col = 0; col < n; col++) { c[row] = col; //如果可以放在row行col列則繼續擺放下一行 if (isOk(c, row, n)) queen(row+1, c, n, total); //如果不可以放在row行col列則試試下一列 } //如果循環了所有的列都不能擺放,則會回溯到前一層函數改變上一行皇后的擺放 } } bool isOk(int c[], int row, int n) { for (int i = 0; i < row; i++) { //第row行皇后不能和任意之前的皇后在同一列或 \方向或 / 方向 if (c[i] == c[row] || c[row]-row == c[i]-i || c[row]+row == c[i]+i) return false; } return true; }
算法是逐行安排皇后的,其參數row為現在正執行到第幾行(row是從0開始的,0表示第一行)。n是皇后數。
參考博客:https://www.cnblogs.com/bigmoyan/p/4521683.html