演算法 八皇后問題

2021-09-19 06:42:09 字數 1568 閱讀 8702

問題描述:

八皇后問題是乙個以西洋棋為背景的問題:如何能夠在8×8的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題:這時棋盤的大小變為n×n,而皇后個數也變成n。當且僅當n = 1或n ≥ 4時問題有解。

解法:

最初的想法是暴力解法,即每一步都有8*8種可能性,8步棋的時間複雜度為。然後按照當前這步棋不能與前面所有棋衝突的原則,排除掉不合法的下法。這種方法的時間複雜度過高。

但其實仔細思考下這個問題,就會發現其獨特性:那就是棋子總共有8個,而棋盤總共為8行8列。也就是說所有的棋子必然在不同行,同時也必然在不同列。每行都有且只有乙個棋子,否則就是不合法的。這個規律可以極大的縮小搜尋空間,比如:第一行必然有乙個棋子,該棋子只有8個可選格仔,而不是64個。

如果當前行號cur==8,則表明已經生成了8個合法的棋子位置,輸出對應陣列lst。

如果當前行號cur==0,此時棋盤上沒有棋子,首行8個位置全都是合法的。

對於首行的每個合法棋子,採用回溯演算法計算下一行的合法棋子位置,即queen(lst,cur+1)。

如果cur>0且cur!=8,則需要判斷當前行可選的8個棋格中,哪些與此前已有的棋子是不衝突的。

只要與已有棋子中的任意乙個衝突,則不合法,可以跳出嘗試下乙個位置。

如果與已有棋子全都不衝突,則找到乙個當前行合法的位置,將其記錄下來。並且用回溯演算法計算下一行的合法位置。

cnt=0

# lst是1*8的輸出陣列,代表棋子在各行的位置,lst中元素的索引表示對應的行號

# cur代表當前行號

def queen(lst,cur):

# 第9行

global cnt

if cur==8:

print lst,cnt

cnt+=1

return

# 首行特殊處理

if cur==0:

for col in range(8):

lst[cur]=col

queen(lst,cur+1)

else:

# 對每一行cur,搜尋各列

for col in range(8):

# 標誌位必須放在下一層迴圈外

tag=true

# 對於內層迴圈中的每乙個元素(對應此前的所有棋子),當前行都必須與其不衝突

for i,j in enumerate(lst[:cur]):

# 如果衝突:列相同,或者在同一斜線上

# 注意,不能abs(j-i)==abs(col-cur),這樣會過濾掉合法結果

if col==j or j-i==col-cur or (i+j)==(cur+col):

tag=false

break #跳出內層迴圈

# 如果不衝突

if tag:

lst[cur]=col

queen(lst,cur+1)#搜尋下一層

queen([none]*8,0)

演算法 八皇后問題

問題簡述 八皇后問題是乙個以西洋棋為背景的問題 如何能夠在8 8的西洋棋棋盤上放置八個皇后,使得任何乙個皇后都無法直接吃掉其他的皇后?為了達到此目的,任兩個皇后都不能處於同一條橫行 縱行或斜線上。八皇后問題可以推廣為更一般的n皇后擺放問題 這時棋盤的大小變為n1 n1,而皇后個數也變成n2。而且僅當...

演算法 八皇后問題

created by xiaoyu on 2019 10 6.include include using namespace std const int n 8 int board n n int tot 0 int valid int x,int y for int i 0 i x i retur...

八皇后問題(回溯演算法)

八皇后問題是古老的問題,十八世紀由乙個西洋棋手提出的,即在乙個8 8 的西洋棋盤上,放置八個皇后,使它們不能相互攻擊到。即不能處於同一行,同一列,也不能處於同一條斜線上,問有多少種擺法。八皇后問題是經典的回溯演算法問題,後人利用計算機,算出了8 8 的棋盤上能擺出92種,而後又提出了n皇后問題。本人...