问题解析:
八皇后问题是一个经典的数学问题,它要求在一个8×8的棋盘上放置8个皇后,使得任意两个皇后都不能互相攻击,即不能处于同一行、同一列或同一对角线上。这个问题可以通过回溯算法来解决。
整体思路:
回溯算法是一种穷举搜索的方法,它通过尝试所有可能的解,并逐步构建解决方案。对于八皇后问题,可以从第一行开始,依次尝试每一列,然后递归地向下一行继续放置皇后,如果这一行中并没有合适的列来放置皇后,则回到上一步,从新选择上一行的放置位置,直到找到一个合法的解,或者所有可能的情况都尝试完毕。
代码实现:
创建了四个辅助数组:locate、error_col、On_diagonal和Low_diagonal,分别用于记录皇后在某一行的位置(也就是在某一行的某一列)、列是否可用、上对角线是否可用,(发现上对角线都等于用行和列所在的序号相加)和下对角线是否可用(发现上对角线都等于用行和列所在的序号相减,为避免出现负数的情况所以加上n-1)。然后定义递归函数eight_queens(row),参数row表示当前要放置皇后的行数。在每一行中,通过循环遍历每一列,判断该位置是否可以放置皇后。判断的条件是:该列未被占用、上对角线未被占用、下对角线未被占用。初始化时未占用的标记为0,如果被占用则标记为1。如果当前位置可以放置皇后,则更新辅助数组locate也就是皇后的相应位置,并且更新放了这个皇后后被占用的位置,然后判断是否已经放置完所有皇后。如果没有放置完,则递归调用eight_queens(row + 1)继续放置下一行的皇后。如果已经放置完所有皇后,则计数器count加1,并输出当前的皇后摆放方式。在回溯过程中,回溯通俗来说就是这一行没有可以放置皇后的列,然后需要将辅助数组的相应位置恢复为可用状态,置为0,以便继续尝试其他可能的摆放方式或者说已经放置了八个皇后之后我们也要将上一步占用的位置即为零,然后回溯寻找还有可能的解。最后,调用eight_queens(0)开始从第0行开始放置皇后,并输出总共有多少种不同的摆放方式。
示例👇
n = 8
locate = [0 for i in range(n)] # 表示皇后放在第几行的第几列
error_col = [0 for i in range(n)] # 表示第几列已不能放皇后
On_diagonal = [0 for i in range(n * 2 - 1)] # 表示上对角线上已不能放皇后
Low_diagonal = [0 for i in range(n * 2 - 1)] # 表示下对角线上已不能放皇后
count = 0 # 计数共有多少种方法
def eight_queens(row):
global count
for col in range(n):
if error_col[col] == 0 and On_diagonal[col + row] == 0 and Low_diagonal[row - col + n - 1] == 0:
locate[row] = col
error_col[col] = 1
On_diagonal[col + row] = 1
Low_diagonal[row - col + n - 1] = 1
if row < n - 1:
eight_queens(row + 1)
else:
count += 1
# 输出
print("第", count, "种")
for i in range(n):
for j in range(n):
if locate[i] == j:
print("*", end=" ")
print("0", end=" ")
print()
# 如果没有这一行无合适位置放皇后则回溯or已经放完了八个皇后则继续寻找
error_col[col] = 0
On_diagonal[col + row] = 0
Low_diagonal[row - col + n - 1] = 0
eight_queens(0)
print(count)