python实现经典的DFS算法-n皇后问题

题目描述:

在 n\times nn×n 的棋盘上放置 nn 个皇后,求所有的放置方法。

放置时要满足:任意两个皇后不能在同一行、同一列,也不能在同一条对角线上。

给定 nn,输出所有合法的放置方案。

输入格式

一个整数 nn。

输出格式

每个解占 nn 行,其中第 ii 行为皇后所在的列编号,按字典序从小到大输出所有的解,每个解之间要用一个空行隔开。

最后一行输出总方案数。

样例输入

4

样例输出

2 4 1 3 3 1 4 2

4 2 1 3 2 4 3 1

解析:

这道题是一个经典的 “八皇后问题”,它的思路是深度优先搜索 + 剪枝。

我们可以从第 11 行开始往下依次考虑放哪个位置的皇后,尝试将其放在 1\sim n1∼n 中的第 ii 列,并判断是否合法。若该位置合法,再考虑填下一行;若不合法则直接跳过这个位置。

在搜索时,我们需要维护三个状态:

  • cols[i] 表示第 i 行上哪一列有皇后
  • diagonal[i-j+n] 表示右上至左下的斜线上是否有皇后,其中 nn 为棋盘大小, ii 与 jj 是该位置的行列号。
  • anti_diagonal[i+j] 表示左上至右下的斜线上是否有皇后,其中 ii 与 jj 是该位置的行列号。

每次循环枚举的是 1\sim n1∼n 中的第 ii 列,如果在同一列(cols[i])或者对角线上(diagonal[i-j+n] 或 anti_diagonal[i+j])已经有了皇后,则直接跳过。否则就将当前位置标记为皇后,并更新三个状态的值,然后进入下一层递归搜索。

终止条件是当前搜索到了最后一行,即搜索到第 n+1n+1 行。

最后,我们统计合法解的数量,并输出所有合法方案。

详细python代码:

def solveNQueens(n: int) -> List[List[str]]:
    def dfs(row):
        # 搜索到了第 n + 1 行,记录答案
        if row == n:
            res.append([''.join(s) for s in board])
            return
        
        for col in range(n):
            # 判断当前位置能否放置皇后
            if not cols[col] and not diagonal[row - col + n] and not anti_diagonal[row + col]:
                cols[col] = True
                diagonal[row - col + n] = True
                anti_diagonal[row + col] = True
                board[row][col] = 'Q'
                
                dfs(row + 1)
                
                cols[col] = False
                diagonal[row - col + n] = False
                anti_diagonal[row + col] = False
                board[row][col] = '.'
        
    res = []
    # 初始化棋盘为全空状态
    board = [['.' for _ in range(n)] for _ in range(n)]
    # 列
    cols = [False] * n
    # 右上至左下的斜线
    diagonal = [False] * (2 * n - 1)
    # 左上至右下的斜线
    anti_diagonal = [False] * (2 * n - 1)
    
    dfs(0)
    
    return res

其中,dfs 函数是核心搜索函数,其参数 row 表示当前正在搜索第几行。在搜索过程中,我们维护了四个状态:棋盘状态 board、列状态 cols、右上至左下的斜线状态 diagonal 和左上至右下的斜线状态 anti_diagonal。在搜索到第 n+1 行时,我们将当前棋盘状态加入到答案中。

主函数初始化了棋盘和四个状态,并从第 0 行开始调用 dfs 函数进行搜索,最终返回答案。

注意:本代码使用了 Python 中的 Type Hints,需要 Python 3.5 及以上版本才能运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

个人练习生xx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值