N皇后問題 回溯與遞迴 C 實現

2021-08-17 07:07:19 字數 1503 閱讀 8304

問題描述:n皇后問題是乙個古老而著名的問題,是回溯演算法的典型案例。該問題由西洋棋棋手馬克斯·貝瑟爾於2023年提出。在西洋棋上,n皇后問題變成了8皇后問題,著名的數學家高斯認為有76種方案,後來有人用圖論的知識解出92種結果,計算機發明後,可以通過演算法實現問題的求解。顯然,大數學家有時候也會敗在計算機面前。8皇后問題是指在8*8的棋盤上擺放8個皇后,使得任意兩個皇后都不在同一行、同一列或者同一斜線上,求滿足這種擺放的解為多少個。(答案是92種)

現在需要分析以下問題:

1.如何擺放才能不重複也不遺漏?

很顯然,我們可以模擬手工擺放:我們逐列放皇后(從小到大逐列擺放),現在先給第一列放皇后,很顯然我們會把它放在第一行,接下來,給第二列放皇后,那麼第二列的皇后能放在哪些位置?這時候需要乙個判斷函式來判斷第二列的皇后能放在那裡。如果第二列找到放皇后的某一行,那麼就進行第三列的擺放,這裡就是遞迴

如果還沒有進行到最後一列的擺放時就已經不能再放皇后,那麼此時需要怎麼做?就返回遞迴的前面一次,把當前列的前面一列的皇后放在後面的行數上(從小到大逐行檢驗)。如果此時逐行檢驗已經遍歷完所有的行數還是出現上面不能擺放的情況,那就在再返回上一次的遞迴,在進行逐行檢驗。這裡就是回溯

為方便描述,我們定義乙個一維陣列pos[i]表示皇后所在位置:設pos[i]=j,則表示第i列的皇后放在第j行上。

2.遞迴的終止條件是什麼?

由初始條件知道,第一行第一列放皇后,那麼會不會有第一行第一列不放皇后的情況呢?我們能不能把這個位置放空,然後把第一列的皇后放在第二行上,或者更後面的一行。答案是肯定能的。那麼問題來了,程式在執行到什麼時候會進行這樣的處理?當第一行第一列放皇后的所有情況都已經遍歷完之後,就會把第一列的皇后放在第二行上,再把這個情況都遍歷完,然後又把第一列的皇后放在第三行上,依次類推,直到把第一列的皇后放在最後一行上,當遍歷完成時,遞迴終止。

以下為c++實現的**:(已經除錯執行成功)

#include#include#includeusing namespace std;

#define max 20 //表示最大的棋盤邊長,可以自定義為其它資料

int pos[max+1]; //為什麼只需要定義乙個一維陣列就能描述二維的棋盤?

//pos[i]是這樣定義的:即第i列的皇后放在第pos[i]行上,

// 也就是說,pos[i]的索引i代表皇后所在的列,它的值pos[i]代表皇后所在的行

int n; //棋盤的邊長和皇后的數量

int sum; //可以成功擺放的數量,每次遍歷成功就加1

bool checknq(int col){ //對第col之前的列進行逐列檢查,pos[i]中i的值為列,pos[i]的值為行

for(int i=1;i>n;

dfsnq(1,n); //傳入第一列和n,從第一列開始放皇后。

cout《筆者水平有限,不足之處希望各位讀者不吝賜教。

n皇后 回溯遞迴

遞迴回溯方法解決 n皇后問題 include include include using namespace std void queen int row int c 遞迴回溯本體 int is true int row int c 判斷是否當前旗子擺放符合條件 int n total 0 int ...

n皇后問題遞迴演算法(回溯法)

n皇后問題遞迴演算法 include include include using namespace std define queen 8 皇后個數 define maxr queen 2 棋盤大小 char chess maxr maxr 定義乙個棋盤 int count 0 總擺放方法 初始化棋...

2 3 遞迴 回溯 N皇后問題

分析 任意兩個皇后都不能處於同一行 同一列或同一斜線上。在第n行已放好的條件下,嘗試第n 1行,如果第n 1行均不滿足,嘗試n行的下乙個可能位置。回溯 在搜尋的過程中嘗試找到問題的解,如果發現找不到了,就退一步,往上回溯 剪枝過程 對於許多複雜問題和大規模問題都可以使用回溯法。按選優條件向前搜尋,以...