【回溯算法】【Python实现】n皇后问题

问题描述

  • n × n n \times n n×n格的棋盘上放置彼此不受攻击的 n n n个皇后,按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子
  • n n n皇后问题等价于,在 n × n n \times n n×n格的棋盘上放置 n n n个皇后,任何 2 2 2个皇后不放在同一行或同一列或同一斜线上

回溯算法

  • n n n元组 x [ 1 : n ] x[1 : n] x[1:n]表示 n n n皇后问题的解, x [ i ] x[i] x[i]表示皇后 i i i放在棋盘的第 i i i行的第 x [ i ] x[i] x[i]
  • 如果将$n \times n $格的棋盘看做二维方阵,其行号从上到下,列号从左到右依次编号为 1 1 1 2 2 2 ⋯ \cdots n n n,从棋盘左上角到右下角的主对角线及其平行线上, 2 2 2个下标值的差值相等,斜率为 + 1 +1 +1的每条斜线上, 2 2 2个下标值的和值相等,若 2 2 2个皇后放置的位置分别是 ( i , j ) (i , j) (i,j) ( k , l ) (k , l) (k,l),且 i − j = k − l i - j = k - l ij=kl i + j = k + l i + j = k + l i+j=k+l,则说明这 2 2 2个皇后处于同一斜线上,由此可知,只要 ∣ i − k ∣ = ∣ j − l ∣ |i - k| = |j - l| ik=jl成立,就表明 2 2 2个皇后位于同一条斜线上
  • 用回溯法解 n n n皇后问题时,用完全 n n n叉树表示解空间
  • 可行性约束剪去不满足行、列和斜线约束的子树
  • i = n i = n i=n时,算法搜索至叶结点,得到一个新的 n n n皇后互不攻击放置方案,当前已找到的可行方案数 s u m sum sum 1 1 1
  • i < n i < n i<n时,当前扩展结点 Z Z Z是解空间中的内部结点,该结点有 n n n个儿子结点,对当前扩展结点 Z Z Z的每个儿子结点检查其可行性,并以深度优先的方式递归地对可行子树搜索,或剪去不可行子树

Python实现

def solve_n_queens(n):
    board = [['.'] * n for _ in range(n)]

    solutions = []

    def is_valid(row, col):
        # 检查当前位置是否可以放置皇后
        for i in range(row):
            if board[i][col] == 'Q':
                return False

            if col - (row - i) >= 0 and board[i][col - (row - i)] == 'Q':
                return False

            if col + (row - i) < n and board[i][col + (row - i)] == 'Q':
                return False

        return True

    def backtrack(row):
        if row == n:
            # 找到一个解决方案
            solutions.append([''.join(row) for row in board])

            return

        for col in range(n):
            if is_valid(row, col):
                board[row][col] = 'Q'

                backtrack(row + 1)

                board[row][col] = '.'

    backtrack(0)

    return solutions


n = 4

solutions = solve_n_queens(n)

print('-' * 5)

for solution in solutions:
    print('\n'.join(solution))

    print('-' * 5)
-----
.Q..
...Q
Q...
..Q.
-----
..Q.
Q...
...Q
.Q..
-----

时间复杂性

  • n n n皇后问题的时间复杂性为 O ( n ! ) O(n!) O(n!)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值