声明:此题为个人方法,仅供参考,如有更简便的方法,欢迎评论区讨论
问题描述:
在一个n*n的棋盘中,我们需要放置n个皇后,使得这n个皇后满足:任意两个都不在同一行,同一列,同一对角线。求解出所有的放置方法。
思路:
这是一个棋盘,这里我们很明显就能想到要用一个二维数组来代表棋盘,当放置一个了皇后,我们就要依条件更新棋盘的元素,这里我们初始化棋盘的初始值为0,如果放置了皇后,依据其皇后的攻击范围来更新棋盘,那么我们又怎么来更新其攻击范围呢?这里我们要设置一个date_attack函数来更新棋盘元素,其条件是要满足在8个方向上,这里我们就可以用两个以为数组一 一对应来代表x,y方向上数值变化,而且变化的话在一个方向上最多只能变化7个位置,如果在某一方向没有这么多位置,例如如果我们放在(1,1)这个位置,而往左上方只有一个位置需要修改,这时我们需要设置一个判断条件x和y的坐标同时满足想x>=0 x<8 y>=0 y<8,这样我们修改的位置就只在这个棋盘内啦。 后面开始从第一行第一列开始寻找,如果合适(if attack[x][i] == 0,不在攻击范围),就更新到下一个状态,并递归寻找第二行满足条件的位置,然后继续更新,又寻找下一行的符合的位置,如果到某一行所有位置都不满足条件了,我们就退回到上一状态,然后判断上一状态后面的那个位置,依次类推,所有的位置就可以找出来啦。还有为了能更清楚地看出棋盘的放置方法,我们还可以设置一个二维数组来表示放置的位置,用Q表示皇后放置的位置,"."表示未放置的位置,满足条件的皇后的位置将此处的 "." 更新为"Q",并继续寻找下一行符合的位置,同上操作,不符合又退回到上一状态。
输入:
n = 8
输出:
小伙伴可以自己试试哟
代码段
import numpy as np
import sys
n = 8 # 自己输入n的值
counts = []
def date_attack(a, b, attacks):
x = [-1, 1, 0, 0, -1, 1,- 1, 1] #代表8个方向
y = [0, 0, -1, 1, -1, -1, 1, 1]
attacks[a][b] = 1
for i in range(n):
for j in range(8): #更新8个方向
dx = a + i*x[j]
dy = b + i*y[j]
if dx >= 0 and dx < n and dy >= 0 and dy < n: #满足条件即可更新
attacks[dx,dy]=1
def backtrack(k, attacks, queens): #回溯法进行求解
if k == n: #达到了最后一行即可输出
solve = np.zeros(shape=(n, n))
solve = queens.copy()
print(solve)
counts.append(1)
if k < n: # 未达到最后一行还需继续寻找
for i in range(n): # 找每一行的8个位置
if attacks[k][i] == 0: # 不在攻击范围内
temp = np.zeros(shape=(n, n))
temp = attacks.copy()
queens[k][i] = "Q"
date_attack(k, i, attacks) #更新棋盘
backtrack(k+1, attacks, queens) #寻找下一行满足条件的位置
attacks = temp
queens[k][i] = "."
print("\n*************\n")
sys.setrecursionlimit(1000000)
attack = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]])
queen = np.array([[".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."], [".", ".", ".", ".", ".", ".", ".", "."]])
backtrack(0, attack, queen)
print("{}种".format(len(counts))) #多少种放置方法
print("\n*************\n")
最后,点个关注点个赞再走吧,谢谢大家