python解决八皇后问题

要将八个皇后放在棋盘上,条件是任何一个皇后都不能威胁其他皇后,即单个皇后的同一行、同一列以及上下左右45°角的方向上都没有其他皇后。

解题思路:每一行、每一列都只能放一个皇后,所以从第一行出发,对于第一行来说,它有八个位置可以选择,需要对这八个位置进行遍历,而对第二行来说,它的选择就小于八个,同样对这些位置进行遍历,以此类推,越到后面的行,其选择越少,所以采用递归的方法,单个递归结束的标志有两个,1)下一行没有位置可选,2)成功递归到最后一行则表明结果之一的出现,将其保存起来。

如下图所示:递归到第五行后,无论怎么选,第六行都没有位置可选,表明第四行的当前选择无解
在这里插入图片描述

对于每一行的皇后来说,它其实都有八个位置可选,只不过因为之前的皇后先做了选择,导致这八个位置中的一部分不可选,所以我们可以用一个状态表来表示哪些位置已经被选过了:

# state = [0, 2, 4] 表示第0列,第2列,第4列已有皇后
# next_x 表示当前行的选择,0-7
# 此处是为了选择当前行的列
def conflict(state, next_x):
    next_y = len(state) # 计算当前所处的列
    for i in range(next_y): # 遍历state中的值
    	# 如果当前行的列与之前皇后的列重合或者在一条对角线上,表明这个位置不可选
        if abs(next_x - state[i]) in (0, next_y - i):
            return False
    return True
# 计算所有可能的组合,queen_nums是皇后的数量,八皇后问题就等于8,还可以计算任意数量的皇后
# depth是深度,即当前处于第几行,用于判断是否结束递归
# state存储的哪些行已被占据
def queens(queen_nums, depth, state):
    res = []
    # 走到最后一行时,如果有位置可选,则结果之一出现,将其保存起来
    if depth == queen_nums - 1:
        for i in range(queen_nums):
            if conflict(state, i):
                res.append([i])
    else:
        for i in range(queen_nums):
            if conflict(state, i):
            	# 从后往前存储结果
                for kk in queens(queen_nums, depth + 1, state + [i]):
                    res.append(kk + [i])
    return  res

完整代码

def conflict(state, next_x):
    next_y = len(state)
    for i in range(next_y):
        if abs(next_x - state[i]) in (0, next_y - i):
            return False
    return True

def queens(queen_nums, depth, state):
    res = []
    if depth == queen_nums - 1:
        for i in range(queen_nums):
            if conflict(state, i):
                res.append([i])
    else:
        for i in range(queen_nums):
            if conflict(state, i):

                for kk in queens(queen_nums, depth + 1, state + [i]):
                    res.append(kk + [i])
    return  res


ww = queens(8, 0, [])
print(len(ww)) # 输出92
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值