算法----解决“八皇后”问题的4种方案

# 第一种:套用子集树模板
# 定义棋盘大小(八皇后问题,所以是8),同时也表示皇后的数量
n = 8
# 用于记录当前尝试放置皇后过程中每一行皇后所在的列位置,初始为空列表
x = []
# 用于存储所有找到的满足八皇后问题条件的皇后放置方案,每个方案也是一个列表,记录每一行皇后所在列位置
X = []

# 判断在第k行放置的皇后是否与前面已经放置的皇后(第0行到第k - 1行)产生冲突
def conflict(k):
    global x
    # 遍历前面已经放置皇后的行(从第0行到第k - 1行)
    for i in range(k):
        # 判断当前放置在第k行的皇后与第i行的皇后是否在同一列
        if x[i] == x[k]:
            return True
        # 判断当前放置在第k行的皇后与第i行的皇后是否在同一对角线上
        # 利用同一对角线上的两个位置,其行索引差的绝对值和列索引差的绝对值相等这一特性来判断
        elif abs(i - k) == abs(x[i] - x[k]):
            return True
    # 如果遍历完前面所有行都没有发现冲突,则返回False
    return False

# 通过递归回溯的方式尝试在棋盘上放置皇后,找出所有满足八皇后问题条件的放置方案
def queens(k):
    global n, x, X
    # 基本情况判断:如果k >= n,意味着已经成功放置了n个皇后(填满了棋盘的每一行)
    if k >= n:
        # 打印当前找到的皇后放置方案
        print(x)
        # 将当前方案x的副本(浅拷贝)添加到列表X中,用于存储所有找到的方案
        X.append(x[:])
    else:
        # 尝试在第k行的每一列(从第0列到第n - 1列)放置皇后
        for i in range(n):
            # 将列索引i添加到列表x中,表示在第k行的第i列放置了皇后
            x.append(i)
            # 检查这个放置是否有冲突,如果没有冲突
            if not conflict(k):
                # 继续递归调用queens函数,去尝试在下一行(第k + 1行)放置皇后
                queens(k + 1)
            # 如果有冲突或者后续放置不符合要求,需要回溯,将刚刚在第k行放置的皇后移除
            x.pop()

# 用于展示给定的一种皇后放置方案对应的棋盘布局情况
def show(z):
    global n
    # 遍历棋盘的每一行(从第0行到第n - 1行)
    for i in range(n):
        # 根据传入的皇后放置方案列表z中记录的每一行皇后所在列位置,打印出相应的棋盘表示
        # 先打印'. '重复z[i]次(表示皇后前面的空白格子),然后打印'X'表示皇后所在位置
        # 接着再打印'. '重复n - z[i] - 1次(表示皇后后面的空白格子)
        print('. ' * z[i] + 'X' + '. ' * (n - z[i] - 1))

# 从第0行开始放置皇后,启动递归回溯过程来寻找所有满足条件的八皇后放置方案
queens(0)
# 打印出存储所有方案的列表X中的最后一个元素,也就是最后一种找到的八皇后放置方案,并换行
print(X[-1], '\n')
# 调用show函数展示最后一种找到的八皇后放置方案对应的棋盘布局情况
show(X[-1])
# 第二种:通过回溯算法实现条件过滤
# 定义棋盘的最大坐标,即8x8的棋盘
max_coordinate = 8

# 初始化一个列表来存储每一列放置皇后的行号,None表示尚未放置
queen_list = [None] * 8

# 定义一个函数来显示当前棋盘的状态
def show():
    column = 0
    while column < max_coordinate:
        # 打印每一列的皇后位置,格式为 (列, 行)
        print("(%d,%d) " % (column, queen_list[column]), end="")
        column += 1
    print("")

# 定义一个函数来检查当前放置的皇后是否与之前放置的皇后冲突
def check(column):
    for column_2 in range(column):
        # 检查是否在同一行
        if queen_list[column_2] == queen_list[column]:
            return False
        # 检查是否在同一对角线
        elif abs(queen_list[column_2] - queen_list[column]) == column - column_2:
            return False
    return True

# 定义一个递归函数来尝试在每一列放置皇后
def put_queen(column):
    for row in range(max_coordinate):
        queen_list[column] = row
        if check(column):
            if column == max_coordinate - 1:
                # 如果已经放置了所有皇后,打印当前棋盘状态
                show()
            else:
                # 递归地在下一列放置皇后
                put_queen(column + 1)

# 定义主函数,从第一列开始尝试放置皇后
def main():
    put_queen(0)
    print("-" * 10)

# 如果这是主模块,则执行主函数
if __name__ == '__main__':
    main()



# 第三种:递归回溯
def queen(queen_list, current_column=0):
    # 棋盘的大小
    size = len(queen_list)

    # 如果已经放置了所有皇后,打印当前的解
    if current_column == size:
        for i in range(size):
            print("(%d,%d)" % (i, queen_list[i]), end="")
        print(" ")
        return

    # 尝试在当前列的每一行放置皇后
    for row in range(size):
        # 假设当前行可以放置皇后
        flag = True

        # 检查当前行是否与之前放置的皇后冲突
        for column in range(current_column):
            if (queen_list[column] == row) or (abs(row - queen_list[column]) == current_column - column):
                flag = False
                break

        # 如果当前行没有冲突,则放置皇后并递归到下一列
        if flag:
            queen_list[current_column] = row
            queen(queen_list, current_column + 1)


# 初始化棋盘,None表示尚未放置皇后
queen([None] * 8)


# 第四种:判断皇后的落点是否合规
import random
# 检查在给定的皇后放置状态下,下一个皇后放置在指定列(nextX)是否会产生冲突
def conflict(state, nextX):
    # 冲突检测函数,用于判断新放置的皇后是否与已放置的皇后冲突。
    # 参数:
    # - state: 一个元组,表示已经放置的皇后的列位置信息,例如(1, 3)
    # 表示第1列皇后在第2行(索引从0开始),第2列皇后在第4行。
    # - nextX: 一个整数,表示下一个皇后要放置的列位置(对应的行位置还未确定,这里通过此函数判断可行性)。
    # 返回值:
    # - 如果新放置的皇后与已放置的皇后存在冲突(在同一行、同一对角线),则返回True;否则返回False。
    nextY = len(state)  # 获取已放置皇后的数量,也就是下一个皇后要放置的行坐标(棋盘是按行列表示,这里用行数来对应纵坐标)
    for i in range(nextY):
        # 检查是否在同一行(state[i] - nextX 的差值为0表示在同一行)或者在同一对角线(差值的绝对值等于行与列的差值绝对值)
        if abs(state[i] - nextX) in (0, nextY - i):
            return True
    return False
# 通过递归生成器的方式来生成所有满足条件的皇后放置方案
def queens(num, state=()):
    # 递归生成器函数,用于生成指定数量皇后在棋盘上的所有满足条件的放置方案。
    # 参数:
    # - num: 一个整数,表示皇后的总数量,也就是棋盘的边长(例如num为8表示8x8的棋盘放置8个皇后)。
    # - state: 一个元组,用于记录已经放置的皇后的列位置信息,默认初始为空元组,表示还未开始放置皇后。
    # 返回值:
    # - 生成器对象,每次迭代返回一个元组,表示一种皇后放置方案,元组中的每个元素代表对应列皇后所在的行位置。
    for pos in range(num):
        if not conflict(state, pos):
            # 如果已经放置了num - 1个皇后(即只差最后一个皇后就全部放置完成),则返回当前皇后位置的元组作为一种方案
            if len(state) == num - 1:
                yield (pos,)
            else:
                # 如果还没到只差最后一个皇后的情况,继续递归调用queens函数,传入更新后的状态(已放置皇后位置信息)
                for result in queens(num, state + (pos,)):
                    yield (pos,) + result
# 用于以可视化的形式打印出皇后放置方案在棋盘上的样子
def prettyprint(solution):
    # 函数用于将皇后放置方案以直观的棋盘形式打印出来,用
    # '.'
    # 表示空白格子,'x'
    # 表示皇后所在位置。
    # 参数:
    # - solution: 一个元组,表示一种皇后放置方案,元组中的元素对应各列皇后所在的行位置。
    def line(pos, length=len(solution)):
        # 内部函数,用于生成表示一行棋盘布局的字符串,根据皇后所在的列位置(pos),在相应位置放置
        # 'x',其余位置用
        # '.'
        # 填充。
        # 参数:
        # - pos: 一个整数,表示皇后在当前行所在的列位置。
        # - length: 一个整数,默认取solution的长度,表示棋盘的总列数,也就是皇后的总数量。
        # 返回值:
        # - 一个字符串,表示一行棋盘的布局情况。
        return '.' * (pos) + 'x' + '.' * (length - pos - 1)
    for pos in solution:
        print(line(pos))
if __name__ == "__main__":
    solutions = list(queens(8))  # 获取所有的皇后放置方案列表
    for solution in solutions:
        prettyprint(solution)  # 逐个打印每个方案对应的棋盘布局
        print("-" * 20)  # 打印分隔线,方便区分不同的方案展示
返回结果:
第一种:

第二种:

第三种:
 

第四种:
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

luky!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值