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))