1. 程式人生 > >八皇后問題--遞歸回溯演算法(Python實現)

八皇后問題--遞歸回溯演算法(Python實現)

前兩天做牛客的時候遇到了一個字串的全排列問題。順便回顧一下八皇后問題。(後附Python程式碼)

如何解決八皇后問題?

所謂遞歸回溯,本質上是一種列舉法。這種方法從棋盤的第一行開始嘗試擺放第一個皇后,擺放成功後,遞迴一層,再遵循規則在棋盤第二行來擺放第二個皇后。如果當前位置無法擺放,則向右移動一格再次嘗試,如果擺放成功,則繼續遞迴一層,擺放第三個皇后......

如果某一層看遍了所有格子,都無法成功擺放,則回溯到上一個皇后,讓上一個皇后右移一格,再進行遞迴。如果八個皇后都擺放完畢且符合規則,那麼就得到了其中一種正確的解法。


解決八皇后問題,可以分為兩個層面:

1.找出第一種正確擺放方式,也就是深度優先遍歷。


2.找出全部的正確擺放方式,也就是廣度優先遍歷。


研究程式碼實現過程中,要解決以下幾個問題:

1.國際象棋的棋盤如何表示?

很簡單,用一個長度是8的二維陣列來表示即可。

2.如何判斷皇后的落點是否合規?

定義一個conflict方法,傳入新皇后的落點,通過縱向和斜向是否存在其他皇后來判斷是否合規。

3.如何進行遞歸回溯?

遞歸回溯是本演算法的核心,程式碼邏輯有些複雜

4.如何輸出結果?

這個問題很簡單,直接遍歷二維陣列並輸出就可以。

5.如何把這些方法串起來?

在main函式裡分三步來呼叫:

第一步:初始化

第二步:遞迴擺放皇后

第三步:最後輸出結果。

#coding=UTF-8
import random
#衝突檢查,在定義state時,採用state來標誌每個皇后的位置,其中索引用來表示橫座標,基對應的值表示縱座標,例如: state[0]=3,表示該皇后位於第1行的第4列上
def conflict(state, nextX):
    nextY = len(state)
    for i in range(nextY):
        #如果下一個皇后的位置與當前的皇后位置相鄰(包括上下,左右)或在同一對角線上,則說明有衝突,需要重新擺放
        if abs(state[i]-nextX) in (0, nextY-i):
        # 表示如果下一個皇后和正在考慮的前一個皇后的水平距離為0或者垂直距離相等,就返回TRUE,否則返回False
            return True
    return False

#採用生成器的方式來產生每一個皇后的位置,並用遞迴來實現下一個皇后的位置。
def queens(num, state=()):
    for pos in range(num):
        if not conflict(state, pos):
            #產生當前皇后的位置資訊
            #如果只剩一個皇后沒有放置
            if len(state) == num-1:
                yield (pos, )
            #否則,把當前皇后的位置資訊,新增到狀態列表裡,並傳遞給下一皇后。
            #程式要從前面的皇后得到包含位置資訊的元組(元組不可更改)
            #並要為後面的皇后提供當前皇后的每一種合法的位置資訊
            #所以把當前皇后的位置資訊,新增到狀態列表裡,並傳遞給下一皇后。
            else:
                for result in queens(num, state+(pos,)):
                    yield (pos, ) + result


#為了直觀表現棋盤,用X表示每個皇后的位置
def prettyprint(solution):
    def line(pos, length=len(solution)):
        return '. ' * (pos) + 'X ' + '. '*(length-pos-1)
    for pos in solution:
        print line(pos)
    for item in queens(8):
        print item

if __name__ == "__main__":
    prettyprint(random.choice(list(queens(8))))

length = len(queens(8))        #92種

for item in queens(8):

    print item                        #輸出每一種表示

輸出如下一種結果:


參考資料:1.書圈 的一個漫畫 “什麼是八皇后問題”點選開啟連結

                2.[挪]Python基礎教程9.9節八皇后問題