N皇后问题

N皇后问题和数独有点相似

问题描述:将N个皇后分别放进NxN的宫格里面,同时满足这N位皇后中的任意相邻两个皇后不在一条直线或对角线上。

"""
python3.9
八皇后问题:在8*8宫格中,要把八个皇后摆在里面,规则
"""


def conflict(state, nextColumn):
    """
    判断是否冲突
    因为坐标是从0开始的,所以state的长度代表了下一行的行坐标
    state:标记每行皇后所在的位置
    nextColumn:下一行的列坐标
    """
    nextRow = rows = len(state)  # 5
    for row in range(rows):  # 0,1,2,3,4
        # 获取当前行的列
        column = state[row]
        """
        如何判断是否冲突:
            1. 如果列的差值为0,说明两皇后在同一列
            2. 如果列的差值等于行的差值,说明两皇后在对角线上
        """
        if abs(column - nextColumn) in [0, nextRow - row]:
            return True
    return False


# 采用生成器的方式来产生每一个皇后的位置,并用递归来实现下一个皇后的位置
def queens(num, state=()):
    """
    基于递归采用回溯算法,算出每一种结果
    :param num: 皇后的数量  8
    :param state: 列坐标。初始为空。参数为元组不为列表,因为参数只能为不可变数据类型
    :return:
    """
    # 每一行的列坐标都是从0:7的
    # 0,1,2,3,4,5,6,7
    for pos in range(num):
        # 判断是否冲突,state为空时不冲突
        if not conflict(state, pos):  # 回溯法的体现
            # 如果state的长度为7,即到达了倒数第二行,也就是前7行皇后都已经找到了位置,最后一行又没有冲突,返回最后一行的列坐标
            if len(state) == num - 1:
                # 最后一行的(pos,)=最后一行的result,然后再递归回去求倒数第二行的result
                yield pos,
            else:
                for result in queens(num, state + (pos,)):
                    """
                    递归实现求state:
                        1. 向下递归
                        第一次(行): pos=0,刚开始不会进入if len(state) == num - 1,进入执行else,会执行queens(num, state + (pos, )),
                        第二次(行): 进入else,再调用queens(num, state + (pos, )),递归执行queens(num, state + (pos,) + (pos,))
                        第三次(行): 进入else,再调用queens(num, state + (pos,) + (pos,),递归执行queens(num, state + (pos,) + (pos,) + (pos,))
                        ...
                        第七次(行): 执行和上面的一样,不过此时state的长度为7
                        第八次(行): 执行f len(state) == num - 1:求出最后一行的列坐标(pos,)

                        2.向上递归
                        求出第八行的列坐标,就可以求出第七行的(pos,),返回的是第七行和第八行的列坐标((pos,) + result)
                        根据下一行的结果依次求出上一行的结果;
                        ....
                        最后求出第一行的列坐标,返回整体结果
                    """
                    yield (pos,) + result


# 进行友好展示:为了至关表现棋盘,用X表示皇后的位置
def PrettyPrint(solution):
    def line(pos, length=len(solution)):
        return '.' * pos + 'X' + '.' * (length - pos - 1)

    for pos in solution:
        print(line(pos))


# 可选择是否展示具体的解决方法:默认b=0,可修改参数值为其他任意值即可展示
def Queens(a, b=0):
    if a <= 3:
        s0 = '"%d皇后"问题,没有满足条件的方案' % a
        return s0
    solutions = queens(a)
    index = 0
    if b == 0:
        for index, solution in enumerate(solutions):
            print('%d皇后"问题第%d种解决方案:' % (a, index + 1), solution)
            PrettyPrint(solution)
            print('*' * 50)
    else:
        for index, solution in enumerate(solutions):
            pass
    s = '"%d皇后"问题,共有%d种方案' % (a, (index + 1))
    return s


# print(Queens(3))
# print(Queens(4, 1))
# print(Queens(5))
print(Queens(8))
# print(Queens(10))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值