Python解决2n皇后问题(附详细代码)

问题描述:给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式:输入的第一行为一个整数n,表示棋盘的大小。接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式:输出一个整数,表示总共有多少种放法。
样例输入:
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出:2
样例输入:
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出:0

这是问题描述

看到问题,读完一遍,有点懵逼,遇到这种读一遍不懂的问题一定冷静下来要多读几遍。对于此问题我们可以先放一个皇后,再放另外一个皇后,并且用不同数字代表不同皇后,这里用2代表黑皇后,3代表白皇后。先放置黑皇后。

因为每行都不能有相同皇后,所以放一个皇后后,就要跳到下一行,跳到下一行后要判断该行是否为最后一行,如果是,则判断是黑皇后放完还是白皇后放完。如果是黑皇后放完,则接着放白皇后,如果白皇后放完,则计数器num加一。如果不是最后一行,执行后续代码,在不是1的位置判断是否可以放皇后。代码中s代表当前放的皇后,chess是棋盘,放置皇后方法用lay()函数封装起来了。代码如下:

def lay(row, n, s, chess):  # 放置皇后的函数
    global num
    if row == n:  # 判断是否每行都遍历了
        if s == 2:  # s=2表示黑皇后,s=3表示白皇后
            lay(0, n, 3, chess)  # 黑皇后放完开始放白皇后
        if s == 3:  # 白皇后也放完,计数器加一
            num += 1
        return
    for i in range(n):
        if chess[row][i] != 1:  # 棋盘位置不等于1表示不能放皇后或者位置被皇后占用
            continue
        if check(row, i, s, chess):  # 判断列和对角线是否有相同皇后
            chess[row][i] = s
            lay(row + 1, n, s, chess)  # 遍历下一行
            chess[row][i] = 1

因为每列和对角线上也不能有相同皇后,所以需要检查一下每列和对角线上是否有相同皇后。这个方法用check()函数封装起来了。代码如下:

def check(row, i, s, chess):
    h = row - 1  # h,l分别是行和列
    l = i - 1
    for m in range(row-1,-1,-1):  # 判断同一列是否有相同皇后
        if chess[m][i] == s:
            return False
    while h>=0 and l>=0:  # 判断左上方对角线是否有相同皇后
        if chess[h][l] == s:
            return False
        h -= 1
        l -= 1
    h = row - 1
    l = i + 1
    while h>=0 and l<n:  # 判断右上方对角线是否有相同皇后
        if chess[h][l] == s:
            return False
        h -= 1
        l += 1
    return True

然后把代码整合起来就行了。代码如下:

n = int(input())
chess = [list(map(int,input().split(' ')))for i in range(n)]  # 模拟棋盘
num = 0
def lay(row, n, s, chess):  # 放置皇后的函数
    global num
    if row == n:  # 判断是否每行都遍历了
        if s == 2:  # s=2表示黑皇后,s=3表示白皇后
            lay(0, n, 3, chess)  # 黑皇后放完开始放白皇后
        if s == 3:  # 白皇后也放完,计数器加一
            num += 1
        return
    for i in range(n):
        if chess[row][i] != 1:  # 棋盘位置不等于1表示不能放皇后或者位置被皇后占用
            continue
        if check(row, i, s, chess):  # 判断列和对角线是否有相同皇后
            chess[row][i] = s
            lay(row + 1, n, s, chess)  # 遍历下一行
            chess[row][i] = 1

def check(row, i, s, chess):
    h = row - 1  # h,l分别是行和列
    l = i - 1
    for m in range(row-1,-1,-1):  # 判断同一列是否有相同皇后
        if chess[m][i] == s:
            return False
    while h>=0 and l>=0:  # 判断左上方对角线是否有相同皇后
        if chess[h][l] == s:
            return False
        h -= 1
        l -= 1
    h = row - 1
    l = i + 1
    while h>=0 and l<n:  # 判断右上方对角线是否有相同皇后
        if chess[h][l] == s:
            return False
        h -= 1
        l += 1
    return True

lay(0, n, 2, chess)
print(num)

运行结果:

 

 

点赞支持一下呗

  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ミの为尔傾心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值