目录
任务描述
本关任务:编写一个能求解四皇后问题的 Python 程序。
相关知识
为了完成本关任务,你需要掌握四皇后问题。
四皇后问题
在 n 行 n 列的国际象棋上摆放 n 个皇后,使其不能互相攻击(即任意两个皇后都不能处于同一行、同一列或同一斜线上)。请问有多少种摆法,以及如何摆放这些皇后。这就是经典的 n 皇后问题。如下图所示:
当 n=4 时就成为了四皇后问题。很明显,这种问题我们可以通过搜索技术来进行求解,例如深度优先搜索。
具体步骤如下:
def make(mark):
'''
标记皇后的位置,例如mark[0] = 2, 表示第1行皇后放在第3列的位置
:param mark: 皇后的位置信息
:return: 拼接好的结果
'''
#初始化数组
r = [['X' for _ in range(len(mark))] for _ in range(len(mark))]
#将每一行中皇后的位置用‘Q’代替
for i in mark:
r[i][mark[i]] = 'Q'
#枚举,将原来散的元素连接成字符串
for k, v in enumerate(r):
r[k] = ''.join(v)
return r
def FourQueens(mark, cur, ret):
'''
深度优先搜索的方式求解四皇后问题
:param mark:表示皇后的位置信息,例如[0,1,3,2]表示棋盘的第1行第1列,第2行第2列,第3行第4列,第4行第3列放置了皇后。例如[1, None, None, None]表示第1行第2列放置了皇后,其他行没有放置皇后。初始值为[None,None,None,None]
:param cur:表示当前准备在第几行放置皇后,例如`cur=1`时,表示准备在第`2`行放置皇后。初始值为0
:param ret:表示存放皇后摆放结果的列表,类型为列表。初始值为[]
:return:无
'''
if cur == len(mark):
#********* Begin *********#
# 如果当前行是最后一行,记录一个解,并返回结束此次搜索
ret.append(make(mark))
return
#********* End *********#
#试探处理,将当前行的皇后应该在的位置遍历每一列,如果满足条件,递归调用处理下一行
for i in range(len(mark)):
mark[cur], down = i, True
for j in range(cur):
# 当想在当前位置放皇后会与其他皇后冲突时不放置皇后
if mark[j] == i or abs(i-mark[j]) == cur - j:
down = False
break
if down:
# 准备在下一行找能放置换后的位置
FourQueens(mark, cur+1, ret)
编程要求
根据提示,在右侧编辑器补充代码,完成 FourQueens 函数,实现找出所有可能的皇后摆法。其中:
mark :表示皇后的位置信息,例如 [0,1,3,2] 表示棋盘的第 1 行第 1 列,第 2 行第 2 列,第 3 行第 4 列,第 4 行第 3 列放置了皇后。例如 [1, None, None, None] 表示第 1 行第 2 列放置了皇后,其他行没有放置皇后。
cur :表示当前准备在第几行放置皇后,例如 cur=1 时,表示准备在第 2 行放置皇后。
result :表示存放皇后摆放结果的列表,类型为二维 list。
测试说明
您只需完成 FourQueens 函数中的 Begin-End 段即可,平台会对你编写的代码进行测试,并将所有皇后的摆放方式打印出来。
预期输出:
******************** XQXX XXXQ QXXX XXQX ******************** XXQX QXXX XXXQ XQXX ********************
代码部分
def make(mark):
'''
标记皇后的位置,例如mark[0] = 2, 表示第1行皇后放在第3列的位置
:param mark: 皇后的位置信息
:return: 拼接好的结果
'''
#初始化数组
r = [['X' for _ in range(len(mark))] for _ in range(len(mark))]
#将每一行中皇后的位置用‘Q’代替
for i in mark:
r[i][mark[i]] = 'Q'
#枚举,将原来散的元素连接成字符串
for k, v in enumerate(r):
r[k] = ''.join(v)
return r
def FourQueens(mark, cur, ret):
'''
深度优先搜索的方式求解四皇后问题
:param mark:表示皇后的位置信息,例如[0,1,3,2]表示棋盘的第1行第1列,第2行第2列,第3行第4列,第4行第3列放置了皇后。例如[1, None, None, None]表示第1行第2列放置了皇后,其他行没有放置皇后。初始值为[None,None,None,None]
:param cur:表示当前准备在第几行放置皇后,例如`cur=1`时,表示准备在第`2`行放置皇后。初始值为0
:param ret:表示存放皇后摆放结果的列表,类型为列表。初始值为[]
:return:无
'''
if cur == len(mark):
#********* Begin *********#
# 如果当前行是最后一行,记录一个解,并返回结束此次搜索
ret.append(make(mark))
return
#********* End *********#
#试探处理,将当前行的皇后应该在的位置遍历每一列,如果满足条件,递归调用处理下一行
for i in range(len(mark)):
mark[cur], down = i, True
for j in range(cur):
# 当想在当前位置放皇后会与其他皇后冲突时不放置皇后
if mark[j] == i or abs(i-mark[j]) == cur - j:
down = False
break
if down:
# 准备在下一行找能放置换后的位置
FourQueens(mark, cur+1, ret)