N皇后问题和数独有点相似
问题描述:将N个皇后分别放进NxN的宫格里面,同时满足这N位皇后中的任意相邻两个皇后不在一条直线或对角线上。
"""
python3.9
八皇后问题:在8*8宫格中,要把八个皇后摆在里面,规则
"""
def conflict(state, nextColumn):
"""
判断是否冲突
因为坐标是从0开始的,所以state的长度代表了下一行的行坐标
state:标记每行皇后所在的位置
nextColumn:下一行的列坐标
"""
nextRow = rows = len(state) # 5
for row in range(rows): # 0,1,2,3,4
# 获取当前行的列
column = state[row]
"""
如何判断是否冲突:
1. 如果列的差值为0,说明两皇后在同一列
2. 如果列的差值等于行的差值,说明两皇后在对角线上
"""
if abs(column - nextColumn) in [0, nextRow - row]:
return True
return False
# 采用生成器的方式来产生每一个皇后的位置,并用递归来实现下一个皇后的位置
def queens(num, state=()):
"""
基于递归采用回溯算法,算出每一种结果
:param num: 皇后的数量 8
:param state: 列坐标。初始为空。参数为元组不为列表,因为参数只能为不可变数据类型
:return:
"""
# 每一行的列坐标都是从0:7的
# 0,1,2,3,4,5,6,7
for pos in range(num):
# 判断是否冲突,state为空时不冲突
if not conflict(state, pos): # 回溯法的体现
# 如果state的长度为7,即到达了倒数第二行,也就是前7行皇后都已经找到了位置,最后一行又没有冲突,返回最后一行的列坐标
if len(state) == num - 1:
# 最后一行的(pos,)=最后一行的result,然后再递归回去求倒数第二行的result
yield pos,
else:
for result in queens(num, state + (pos,)):
"""
递归实现求state:
1. 向下递归
第一次(行): pos=0,刚开始不会进入if len(state) == num - 1,进入执行else,会执行queens(num, state + (pos, )),
第二次(行): 进入else,再调用queens(num, state + (pos, )),递归执行queens(num, state + (pos,) + (pos,))
第三次(行): 进入else,再调用queens(num, state + (pos,) + (pos,),递归执行queens(num, state + (pos,) + (pos,) + (pos,))
...
第七次(行): 执行和上面的一样,不过此时state的长度为7
第八次(行): 执行f len(state) == num - 1:求出最后一行的列坐标(pos,)
2.向上递归
求出第八行的列坐标,就可以求出第七行的(pos,),返回的是第七行和第八行的列坐标((pos,) + result)
根据下一行的结果依次求出上一行的结果;
....
最后求出第一行的列坐标,返回整体结果
"""
yield (pos,) + result
# 进行友好展示:为了至关表现棋盘,用X表示皇后的位置
def PrettyPrint(solution):
def line(pos, length=len(solution)):
return '.' * pos + 'X' + '.' * (length - pos - 1)
for pos in solution:
print(line(pos))
# 可选择是否展示具体的解决方法:默认b=0,可修改参数值为其他任意值即可展示
def Queens(a, b=0):
if a <= 3:
s0 = '"%d皇后"问题,没有满足条件的方案' % a
return s0
solutions = queens(a)
index = 0
if b == 0:
for index, solution in enumerate(solutions):
print('%d皇后"问题第%d种解决方案:' % (a, index + 1), solution)
PrettyPrint(solution)
print('*' * 50)
else:
for index, solution in enumerate(solutions):
pass
s = '"%d皇后"问题,共有%d种方案' % (a, (index + 1))
return s
# print(Queens(3))
# print(Queens(4, 1))
# print(Queens(5))
print(Queens(8))
# print(Queens(10))