Python|每日一练|力扣(LeetCode)|深度递归|回溯循环|位运算 :N皇后 II

题目:

 

皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

Python|每日一练|力扣(LeetCode)|深度递归|回溯循环|位运算 :N皇后 II_第1张图片

示例 1:

输入:n = 4

输出:2

解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1

输出:1

 

提示:

  • 1 <= n <= 9
  • 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

以下程序实现了这一功能,请你填补空白处内容:

官方解答注释(位操作为主,需判断出正确选项)

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以内数据计算速度较快

2、位置判断更新法(输出皇后摆放位置及组数)

引用原文: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)

你可能感兴趣的:(每日一练,leetcode,python,深度优先,剪枝,算法)