N皇后問題

2022-05-07 02:30:09 字數 3469 閱讀 8711

八皇后問題(英文:eight queens),是由國際西洋棋棋手馬克斯·貝瑟爾於2023年提出的問題,是回溯演算法的典型案例。

問題表述為:在8x8格的西洋棋上擺放8個皇后,使其不能互相攻擊,即任意兩個皇后都不能處於同一行、同一列或同一斜線上,問有多少種擺法。

高斯(高等數學男神)認為有76種方案,後來有人用圖論的方法解出92種結果。

n皇后問題由八皇后問題衍生而來,即n 皇后問題研究的是如何將 n 個皇后放置在 n×n 的棋盤上,並且使皇后彼此之間不能相互攻擊。

規則解讀
規則:任意兩個皇后都不能處於同一行、同一列或同一斜線上對於行列的判斷,比較直觀,只需檢查對應皇后的行列號即可判斷是否有兩個以上的皇后處於同一行或同一列,而對於判斷是否在同一斜線上,則需要找規律,這裡參照力扣官方的解題思路:

如何定義皇后的位置

可能大多數人的想法是定義每乙個皇后的橫縱座標,但是在實際指定皇后位置的時候,我們是挨個指定的,也就是說,我們不可能同時指定多個皇后的位置,因為略過了判定步驟,會造成位置重複。

因此,我們可用利用這個指定順序,作為皇后的乙個維度的座標,這樣一來,指定皇后位置時,只需要指定乙個座標即可,實際上每個皇后依然有橫縱座標,只不過其中的乙個座標維度被隱藏了。

需要使用的方法
很明顯的,這裡需要用到遞迴演算法,因為即使不使用暴力窮舉,當n增大到一定程度時,所需要做的運算量依然是驚人的。

除此之外,還需要使用到的乙個非常重要的核心方法:回溯演算法。在指定某乙個皇后位置時,如果發現該維度(行/列)的所有位置均得不到結果,則需要重新確定當前維度的位置,也就是說前面指定的皇后位置無法得到結果,需要回退,這裡的回退即是回溯演算法的精髓,即回退只是回退一步,而不是之前的所有工作全部銷毀

8皇后**(力扣官方)
class solution:

def solvenqueens(self, n):

def could_place(row, col):

# 如果列,『上坡對角線』位置值,『下坡對角線』位置值,全部為0,則意味著該位置未放置皇后,可以放置,否則返回false

return not (cols[col] + hill_diagonals[row - col] + dale_diagonals[row + col])

def place_queen(row, col):

queens.add((row, col))

# 放置皇后後,該位置列位置值,『上坡對角線』位置值,『下坡對角線』位置值全部置為1

cols[col] = 1

# 對角線可能經過多個位置,但只要該對角線的乙個位置被放置皇后,則整條對角線經過的位置均不可再放置皇后

hill_diagonals[row - col] = 1

dale_diagonals[row + col] = 1

def remove_queen(row, col):

queens.remove((row, col))

# 清除皇后後,該位置列位置值,『上坡對角線』位置值,『下坡對角線』位置值全部置為0

cols[col] = 0

hill_diagonals[row - col] = 0

dale_diagonals[row + col] = 0

def add_solution():

solution =

# 進行排序,對於元素是元組的集合而言,會按照元組的第乙個元素排序,第乙個元素相同使用第二個,以此類推,排序完成,

# 會將集合轉為列表,由於這裡皇后位置的判定使用的是列位置,行是遞增的,即逐行判斷每一列,所以排序後,即是1-n行

for _, col in sorted(queens):

# 此回溯函式可進可退

def backtrack(row=0):

# 遍歷n次,相當於在第一行的各個列位置確定的條件下,有多少種解法,檢視列印結果找規律

# 每次遞迴,行都是遞增的,

for col in range(n):

if could_place(row, col):

place_queen(row, col)

# 判斷是否完成一次成功放置

if row + 1 == n:

add_solution()

else:

# 遞迴

backtrack(row + 1)

# 回退一步

# 何時回退?正確時回退,錯誤時也會回退

# 確定乙個位置結果後,回退一步,檢視最後一步是否還有其他結果,從後向前遞迴

# 比如,確定8行的列位置(即確定第八個皇后的位置),確定為2列,記錄結果後,回退一步,列序號+1,看一下8行的3-8列是否也可以

remove_queen(row, col)

# 初始化,棋盤每個位置均可放置皇后,位置值均為0

cols = [0] * n

hill_diagonals = [0] * (2 * n - 1)

dale_diagonals = [0] * (2 * n - 1)

queens = set()

output =

backtrack()

return output

if __name__ == '__main__':

eightqueen = solution()

# 輸出結果並列印至文字檔案

for i in range(len(eightqueen.solvenqueens(8))):

with open(r'c:\users\86188\desktop\python_study\homework\.nqueen.txt', 'a') as fp:

print(f'第個解', file=fp)

for j in range(len(eightqueen.solvenqueens(8)[i])):

print(eightqueen.solvenqueens(8)[i][j], '\n', file=fp)

print('\n', file=fp)

fp.flush()

執行結果(前8個,供結果分析)

N皇后問題

include define maxqueens 20 define minqueens 4 enum bool typedef struct queendata queendata queendata queens maxqueens 1 int ncount init int init chec...

N皇后問題

採用遞迴回溯法 執行結果 輸入8 對於n皇后解的個數,參考 當n 16時,構造法給出解,參考poj 3239 一 當n mod 6 2 且 n mod 6 3時,有乙個解為 2,4,6,8,n,1,3,5,7,n 1 n為偶數 2,4,6,8,n 1,1,3,5,7,n n為奇數 上面序列第i個數為...

N皇后問題

問題 題目 於西洋棋的玩法,因為皇后所在的位置可以縱向 橫向 兩個斜向四個方向的 捕捉 所以8皇后問題就是要求如何布置8個皇后在8 8的棋盤上而使他們互相無法 捕捉 也就是說不存在兩個皇后同行或同列,或在同一斜線上。而n皇后問題就是如何布置n個皇后在n n棋盤裡使不存在兩個皇后在同行同列和同一斜線上...