Leetcode演算法——51~52、n皇后問題
阿新 • • 發佈:2018-12-10
n皇后問題需要將n個皇后放置在n*n的棋盤上,保證任意兩個皇后都不能處於同一行、同一列或同一斜線上。
51、給定一個整數n,返回n皇后問題的所有不重複的解。
51、給定一個整數n,返回n皇后問題的所有不重複的解的個數。
每個解都是一種n個皇后的佈局,其中 ‘Q’ 和 ‘.’ 分別代表皇后和空白。
示例:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
思路
n皇后問題是典型的回溯法教材。
所謂回溯法,是在遞迴的基礎上,增加了回溯(即反悔的操作),先假設我採用方法A解決當前問題,然後繼續遞迴剩下的任務,最後回過頭來進行反悔,不這樣做了,而改用方法B來解決這個問題,然後繼續遞迴。
使用回溯法,能夠實現對所有滿足要求情況的列舉,同時最大程度減少不滿足要求的列舉(因為一旦中間某個過程不滿足要求,則剩下的過程不再繼續遞迴)
以n皇后為例,可以這樣做:
- 初始化一個n*n的空棋盤
- 嘗試在第1行第1列中安放一個皇后,判斷放在這裡之後整個棋盤是否尚且滿足要求,如果滿足,則繼續遞迴第2行;如果不滿足,則回溯:將皇后從第1行第1列刪掉,改為放在第1行第2列。
- 繼續判斷放在第1行第2列之後整個棋盤是否滿足要求,以此類推。
- 遞迴結束:一旦最後一行中某一列安放一個皇后,可以使得整個棋盤滿足要求,那麼便求出了一個解。
- 我們要求尋找到所有不重複的解,因此這時演算法還不能結束,繼續回溯:倒數第2行的皇后向右移動一格,繼續遞迴。
- 直至所有迴圈都退出。
python實現
def solveNQueens(n):
"""
:type n: int
:rtype: List[List[str]]
回溯法。
"""
def place_queen(result_list, place_list, cur_row):
'''
在第 cur_row 行上放置一個皇后。
result_list:存放所有的解
place_list:長度為n,每一個元素代表這一行上的皇后的位置
'''
# 遞迴結束條件
if cur_row == len(place_list):
# 將答案轉為二維棋盤,放入到result_list中
# 如果是返回解的個數,則不需要轉為二維棋盤,直接統計result的個數即可
result_list.append(['.'*i + 'Q' + '.'*(n-i-1) for i in place_list])
return
# 在cur_row這一行上對所有位置依次嘗試放置皇后
for cur_col in range(n):
place_list[cur_row] = cur_col
# 判斷是否有同行同列同斜邊的皇后
for row in range(cur_row):
col = place_list[row]
if col == cur_col or abs(cur_col - col) == cur_row - row:
break
else:
# 沒有break,說明有效,繼續放置下一行
place_queen(result_list, place_list, cur_row + 1)
result_list = []
place_queen(result_list, [0] * n, 0)
return result_list
def output_board(board_list):
'''
輸出棋盤
'''
print(f'共{len(board_list)}種解法')
for board in board_list:
print(' ')
for row in board:
print(row)
if '__main__' == __name__:
n = 4
output_board(solveNQueens(n))