n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。
输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。
输入:n = 1
输出:1
以下程序实现了这一功能,请你填补空白处内容:
class Solution(object):
def __init__(self):
self.count = 0
def totalNQueens(self, n):
#self.dfs函数可看做为类的全局函数,该函数的作用是计算类的全局变量self.count,得到所求结果
#self.dfs输入5个初始变量,设置起点为0,0,总数量n,diag, antiDiag初始值也是0
self.dfs(0, n, 0, 0, 0)
return self.count
#row当前行数, column:当前列数,
#diag表示左下方斜线的影响,每次左移一位,递归计算到上一行为止,受到皇后的左下方斜线的影响,导致当前行不能放置皇后,1代表不能放置,0代表可以放置。
def dfs(self, row, n, column, diag, antiDiag):
#递归终止条件
#如果放置完皇后, row == n, 说明在深度递归到这一步的row,col上,可以放置n个皇后的解已全部找出(当前row也是一个解)
# 故self.count +1后退出回溯循环
if row == n:
#计算后self.count=1
self.count += 1
return
#任何两个皇后都不能处于同一条纵行或斜线上,对当前皇后的放在n个位置上的可行性进行判断
#当前测试位置编号为index,range(n)代表从0~ n - 1的n种放法
for index in range(n):
# >> 和 << 属于python 位运算符
# << :左移运算符,相当于乘法操作,运算数的全部二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。
# >> :右移运符:相当于除法,把">>"左边的运算数的各二进位全部右移若干位,>> 右边的数字指定了移动的位数
isColSafe = (1 << index) & column == 0 # 1左移index位(逐个测试每个位置),和上层的column相与为0,则说明该index位没有冲突
# row - index可能为负数,+(n - 1)来防止数组越界
#斜线上的位置是否安全:1左移(列 - 行)位(逐个测试每个位置),和反斜线上层位置值相与等于0,说明斜线位置没有冲突
isDigSafe = (1 << (n - 1 + row - index)) & diag == 0
#反斜线上的位置是否安全:1左移(行 + 列)位(逐个测试每个位置),和反斜线上层位置值相与等于0,说明反斜线位置没有冲突
isAntiDiagSafe = (1 << (row + index)) & antiDiag == 0
#如果以上3个判断都符合,则可进行下一层的测试,更新位置值。
if (isAntiDiagSafe and isColSafe and isDigSafe):
#A
#递归,更新row、column,column为当前层放皇后的位置,(1 << index)|colum为当前层放皇后的列位置,
# 其他类似,同时更新。
self.dfs(row + 1, n, (1 << index)|column,(1 <<(n - 1 + row - index))|diag,(1<<(row + index))|antiDiag)
# B
# self.dfs(row + 1, n, (index >> 1) | column,
# (1 << (n - 1 + row - index)) | diag,
# (1 << (row + index)) | antiDiag)
# C
# self.dfs(row + 1, n, (index >> 1) | column,
# (1 << (n + 1 + row - index)) | diag,
# (1 << (row + index)) | antiDiag)
# D
# self.dfs(row + 1, n, (1 << index) | column,
# (1 << (n + 1 + row - index)) | diag,
# (1 << (row + index)) | antiDiag)
#为测试方便,增加了main()主函数及范例数据:
if __name__ == '__main__':
s = Solution()
print (s.totalNQueens(4)) #测试10以内数据计算速度较快
引用原文:N皇后问题——Python解决(超详细注释)
修改:修改为类模式,增加self.count全局变量,便于统计总共符合的组数,并输出全部皇后摆放位置。
class Solution(object):
def __init__(self):
self.count = 0
def dfs(self,num, res, row):
if row == num:
print(res)
self.count += 1
return
for col in range(num):
if self.check(col, res, row):
res[row] = col
self.dfs(num, res, row + 1)
res[row] = 0
return self.count
def check(self,col, res, row):
for i in range(row):
if res[i] == col or res[i] + i == row + col or res[i] - i == col - row:
return False
return True
if __name__ == '__main__':
s = Solution()
# num: 皇后的数量
num = int(input('请输入皇后的数量:'))
# 最终皇后的位置 (下标:第几行 数值:第几列)
res = [0 for _ in range(num)]
# 从第一行开始
row = 0
# 参数:皇后总数 位置结果 当前放置第几行
count=s.dfs(num, res, row)
print('查找到符合条件的组数:',count)
print('类中的self.count:',s.count)