回溯法解决八皇后问题

问题:

在国际象棋棋盘上(8*8)放置八个皇后,使得任意两个皇后之间不能在同一行,同一列,也不能位于同于对角线上。问共有多少种不同的方法,并且指出各种不同的放法。
在这里插入图片描述

思路:

使用回溯法依次假设皇后的位置,当第一个皇后确定后,寻找下一行的皇后位置,当满足左上、右上和正上方向无皇后,即矩阵中对应位置都为0,则可以确定皇后位置,依次判断下一行的皇后位置。当到达第8行时,说明八个皇后安置完毕。

回溯法实现:

#八皇后问题
board = [
    [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]
]

#total记录多少种方法
total = 0


#判断(x,y)能否放皇后
def can_place(x, y):
    # 判断(x,y)坐标能否放皇后
    # 1. 判断x行是否有皇后
    for i in range(0, y):
        if board[x][i] == 1:
            return False
    # 2. 判断y列是否有皇后
    for i in range(0, x):
        if board[i][y] == 1:
            return False

    # 3. 判断"/"方向是否有皇后
    for i in range(0, x):
        if x + y - i <= 7 and board[i][x + y - i] == 1:
            return False

    # 4. 判断"\"方向是否有皇后
    for index, i in enumerate(range(x - 1, -1, -1)):
        s_y = y - (index + 1)
        if s_y >= 0:
            if board[i][s_y] == 1:
                return False

    return True


#打印
def print_board():
    for i in range(8):
        for j in range(8):
            if board[i][j] == 0:
                print("□ ", end=" ")
            else:
                print("■ ", end=" ")
        print()


#回溯法查找适合的放法
def put_queen(step):
    if step == 8:
        print_board()
        global total
        total += 1
        print("----------------")
    else:
        for i in range(8):
            # 判断该位置是否能放当前皇后
            if can_place(step, i):
                # 1. 设置现场
                board[step][i] = 1
                # 2. 开始递归
                put_queen(step + 1)
                # 3. 恢复现场
                board[step][i] = 0


if __name__ == "__main__":
    put_queen(0)
    print("总共有{}种方法".format(total))

输出

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值