n後問題(python實現)

程序實現

# 檢測(x,y)這個位置是否合法(不會被其他皇后攻擊到)
def check(board, row, col):
    i = 0
    for i in range(row):
        if abs(board[i] - col) == 0 or abs(board[i] - col) == abs(i - row): #[i, j]與[row, col]處於同列或者同對角線上
            return False
    return True


def eightqueen(board, row):
    border = len(board)
    if row >= border:    # 當行數等於最大邊界時,遞歸
        for i, col in enumerate(board): #輸出從第一行到第board行結果
            print('□ ' * col + '■ ' + '□ ' * (len(board) - 1 - col))#■爲皇后位置
        print("")
    col = 0
    while col < border:
        for col in range(border):
            if check(board, row, col): #如果這個位置合法的話,進行如下操作
                board[row] = col
                eightqueen(board, row + 1) #進行遞歸,使得行加一,即進入下一行
        col += 1

board = [0 for i in range(8)] # 8皇后問題 
eightqueen(board, 0)

首先我們要給定一個矩陣,來存放棋子,從第一行開始遍歷,接着遍歷這一行的每一列。假設我們在位置[1, 2]處已經放上棋子,我們開始遍歷第二行,首先判斷[2,1]位置存放棋子是否可行,調用check函數,顯然與上一行棋子處於同一對角線,不行返回False,以此類推直到便利到位置[2,4]時這是一個可行的位置,再繼續往下遍歷。

總結的來說就是在遍歷當前行時,之前行的棋子已經確定好了,從而以此判斷該行的各個位置是否可行。

當然對於主函數來說我們需要一個遞歸終止的條件,很簡單噹噹前行數大於N時,我們就已經得到了一個符合條件的矩陣。

除此之外,我們如果用矩陣存儲,每次都要通過遍歷來確定之前行棋子所在的位置,時間複雜度爆炸。所以這裏做一個簡化,我們用一個[1, n]的矩陣來存儲,也就是說[row, col] = [i, board[i]],這樣我們只需要O(1)的時間複雜度就能知道上一行的信息。

再說check函數,首先我們是一行行進行遍歷,一定不會存在同行的情況,同列也比較好判斷,對於正負對角線,通過觀察我們可以發現,我們設row,col爲當前行當前列,那麼對於位置[i, j]。如果符合等式|row- i| = |col-j|,那麼[i, j]如[row, col]位於同一對角線。把上述兩種情況合併,如果if abs(col - j) == 0 or abs(col - j) == abs(row-i),那麼[i, j]與[row, col]必處於同列或者同對角線上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章