n皇后問題求解

2021-10-23 11:04:23 字數 1994 閱讀 5844

在乙個n×n的棋盤上放置n個王后,使得每個王后不會相互攻擊,即任意兩個王后不在同一行、同一列、同一對角線上,輸出所有的放置方式。

輸入n,表示棋盤大小。

深度優先搜尋(dfs):列舉第i個王后的放法,再列舉第i+1個王后的放置方法,直至放置完所有棋子,檢查放置方式是否合法,若合法則輸出;不合法則返回,嘗試其他放置方式。

公用:bool isvalid(int n) //全部棋子放完之後判斷是否合法的函式,主要判斷任意兩顆棋子是否在同一對角線上

isvalid函式判斷是否在同一對角線上的依據是兩個點(x1,y1),(x2,y2)是否存在x1+y1=x2+y2或x1-y1=x2-y2的情況。函式採用了兩組陣列記錄棋子座標的x和y,同一下標表示同乙個點的x值或y值。

isvalid函式首先通過二重迴圈將n個放置好的棋子的座標單獨取出並記錄,再通過二重迴圈將兩個相鄰的點進行比較,最後全部比較一遍,判斷是否有兩個點在同一對角線上,注意j=i+1的這種迴圈起始模式是判斷相鄰的。

注意:isvalid函式傳參的時候也要注意傳的是sum值,因為isvalid函式是判斷n個棋子是否都放置合法了,所以要用sum,不然n會變。

for(int p=1;p<=n;++p)

for (int k = p+1; k < n + 1; k++) //判斷任意兩個點是否在同一對角線上 }

return true;

注意return true 和return false的位置

設條件a=,若為真,則點(x1,y1)與(x2,y2)在同一對角線上。true要求所有均不滿足條件a,對應地,任一對點(x1,y1)與(x2,y2)滿足條件a,則返回false

由此,在迴圈內進行條件判斷時,一旦if語句為真,則可以返回false

所有判斷語句結束後(即兩重循壞結束後),函式仍未返回值,則說明所有點對均不滿足條件a,才能返回true

樸素解:

nqueen(int n) //其中n表示剩餘待放的棋子數

nqueen的思想就是,遍歷所有格仔,先放置乙個棋子,將棋子所在的座標以及行列設為1(避免在同一行同一列再放置棋子),再少乙個棋子進行遞迴,遞迴後要記得再重置為0,因為會執行到重置那一步說明有棋子放置不合法。

**注意:**nqueen(n)中的n指的是要放置的棋子數目,這個數目隨著遞迴nqueen(n-1)會逐漸變小,所以要用乙個sum值來記錄一開始的n來進行遍歷的計算,免得因為n不斷變小,就沒有全部遍歷。

for (int i = 1; i < sum + 1; i++) 

} }

剪枝1:用兩個陣列(行陣列line和列陣列row)判斷是否同行同列,

for (int i = 1; i < n + 1; i++) 

} }

遺留問題:重複輸出正確解

原因:因為預設所有棋子出現在所有位置的概率相同,所以放置第乙個棋子時,它可能被放置在第一行的正確位置上;但也可能被放置在其他行的正確位置上,而第一行的正確位置被第二個棋子佔據,甚至第三個棋子佔據……由此同乙個解由於放置棋子的順序不同被輸出了多次,但因為棋子沒有編號,這些解都是相同的。

改進:void nqueen2(int n)

nqueen是時間複雜度比較高,nqueen2降低了時間複雜度。nqueen2減少複雜度的操作是,將每一次遍歷的行數固定,因為在n*n的棋盤上放置n個不同行不同列不同對角線的皇后,每一行都必須放置乙個,所以固定了行數就可以減少到一重迴圈。

同時可以解決nqueen中重複輸出解的問題,棋子按行序放置(按列序放置也一樣),乙個正確解只會被搜到一次。

for(int i=1;i其他:

求解n皇后問題

n皇后問題 回溯法 遞迴的邏輯中一般有兩個重要的概念 1.遞迴邊界 2.遞迴式 1.問題描述 在n n格的西洋棋上擺放n個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行 同一列或同一斜線上,問有多少種擺法。遞迴思想 int count 0 void generatep int index i...

使用C 求解N皇后問題。

下面這個演算法實現了列出所有可能放置的情況。using system namespace queen 顯示當前矩陣情況。public void display console.writeline 判斷當前位置是否可以放置皇后。private bool iscurrentcanplaced int r...

回溯法求解N皇后問題。

n皇后問題就是 不存在兩個皇后同行或同列,或在同一斜線上。如下圖所示。黑色塊表示其中乙個皇后放在了第二行,第三列。這時,只有綠色圈圈才能放其他的皇后。回溯法的基本思想 確定了解空間的組織結構後,回溯法就從開始結點 根結點 出發,以深度優先的方式搜尋整個解空間。這個開始結點就成為乙個活結點,同時也成為...