八皇后問題是乙個以西洋棋為背景的問題:如何能夠在8×8的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題:這時棋盤的大小變為n×n,而皇后個數也變成n。當且僅當n = 1或n ≥ 4時問題有解。(問題描述來自參考文獻1)
數學王子高斯當年花費了無數心血,最後計算認為八皇后問題有76種解法,現在我們通過計算機模擬可以輕鬆計算出八皇后問題的真正解法有92種。能讓高斯栽跟頭的問題,可想而知計算的複雜性與難度。
高斯將八皇后的解法推導出76種,已經算是非常厲害了。這不能怨高斯,而是八皇后的計算複雜度確實太高。
該問題的整體思路還是暴力解法
1.先列出所有可能的皇后擺放方式。
2.再檢查該種擺放方式是否符合要求。
具體的執行過程如下:
先將第乙個皇后放在第一行第一列,然後將第二個皇后放在第二行第一列,判斷該種擺法是否符合要求。很明顯這樣擺不行,有兩個皇后會在同一列。再將第二個皇后放在第二行第二列,這樣也不行,兩個皇后會在一條斜線上。將第二個皇后放在第二行第三列,這樣滿足當前條件。
目前已經有兩個皇后滿足條件,接下來放第三個,還是從第三行第一列開始放置,不滿足條件再放第二列,第三列…一直到第8個皇后也能放在乙個不衝突的位置,此時找到乙個符合要求的解。
然後我們開始回溯,將第乙個皇后放在第一行第二列,後面的就繼續按上面的方式迴圈,一直到回溯完畢,找出所有符合條件的解為止。
參考文獻2有張圖,比較詳細的用圖描述了上面的過程,貼出來大家參考。下面圖描述的是4皇后的回溯過程,原理跟8皇后是一致的。
上面原理分析完畢,接下來看**實現。
public class nqueuev2
}for(int m=row-1, n=column+1; m>=0 && n**輸出結果:
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
result is: 2
上面的**,為了方便輸出最後結果,模擬的是4皇后,8皇后只需要將n改為8即可。
board二維陣列,模擬的是棋盤,初始狀態均為0,表示該位置沒有放置皇后。如果該位置設為1,表明該位置有皇后。
k表示放置的皇后個數。如果k==n,說明n個皇后都被放置完畢,此時得到乙個有效解。
for(int row=0; row該部分**輸出有效解的狀態,陣列為1的位置表示該位置放置了皇后。
else部分**,i表示的是第i列,check(k, i)方法表示的是在(k, i)這個位置放置皇后是否合法
for(int i=0; i這部分**,表示兩個皇后不能放置在同一列。
for(int m=row-1, n=column-1; m>=0 && n >= 0; m--, n--)
}
這部分**,表示該皇后的左斜線部分不能有皇后。
for(int m=row-1, n=column+1; m>=0 && n這部分**,表示該皇后的右斜線部分不能有皇后。
如果該位置能放置皇后,則將棋盤中該位置置為1,接下來往下一行放皇后putqueque(k+1)。同時,在回溯的時候,需要將該位置置為0。
所以看上去很複雜的八皇后問題,對著圖,再對著**分析,是不是感覺沒那麼難了?
本質還是經典回溯演算法的使用,跟前面我們講到的排列組合類似。當了解完整個過程以後,回溯的難度甚至比排列組合還小!
史上最全排列組合演算法詳解以及套路總結一文搞定
1.2.
n皇后問題與八皇后
這裡的n皇后問題指在乙個nxn的棋盤上放置n個棋子,使得每行每列和每條對角線上都只有乙個棋子,求其擺放的方法數。當且僅當n 1 或 n 4 時問題有解。class queens vector vector res int result 0 bool test int cur for int i 0 ...
八皇后問題詳細思路分析
static int count 0 共多少解法 public static void main string args 編寫乙個方法,放置第n個皇后 特別主意 check 是每一次遞迴時,進入到check中都有for int i 0 i private void check int n 如果沒有到...
八皇后問題的簡單分析
八皇后問題是乙個以西洋棋為背景的問題 如何能夠在 8 8 的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后。為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。基本思路 將棋盤分為8行,每一行填充乙個棋子,這樣就能保證每一行不衝突,具體到每一行的話,又分為8種可能,顯然...