ACWing【843】n皇后问题

优质博客

n皇后

问题描述

        N 皇后问题是指在 n x n 的棋盘上放置 n 个皇后,使得每个皇后都不能互相攻击。皇后可以在同一行、同一列、同一对角线上攻击其他皇后。因此,问题的核心是如何安排皇后的位置,保证没有两个皇后互相攻击。

 题目

核心思路

  • 初始化棋盘与标记数组:创建一个 n x n 的棋盘,并使用三个布尔数组 row, dg, udg 分别记录每列、主对角线、副对角线上是否已有皇后。

  • 递归搜索与回溯

    • 从第 0 行开始,依次为每一行寻找合适的列(即没有皇后攻击的位置)。
    • 每次找到合法位置后,将其标记为已放置皇后,递归地处理下一行。
    • 如果递归到第 n 行,说明找到了一组可行解,打印当前棋盘。
    • 如果当前行所有列都不满足条件,则回溯到上一行,撤销上一个皇后的放置,并尝试其他位置。
  • 剪枝

    • 使用布尔数组 row, dg, udg,有效地剪枝,减少不必要的搜索。

全局变量定义

const int N=20;
char g[N][N]; // 用于存储棋盘,'Q' 表示皇后,'.' 表示空位
bool row[N],dg[N],udg[N]; // 分别记录列、主对角线、副对角线是否已经有皇后
int n; // 棋盘大小
  • g[N][N]:棋盘,用于表示皇后和空格。
    • g[i][j] = 'Q' :第 i 行第 j 列放置了一个皇后。
    • g[i][j] = '.' :当前位置没有皇后。
  • row[N]:用于记录每一列是否已有皇后,防止同列放置两个皇后。
  • dg[N]udg[N]:分别用于记录主对角线和副对角线是否有皇后。
    • 主对角线:对角线元素满足 i - j 相同。
    • 副对角线:对角线元素满足 i + j 相同(截距b看做第几行,最后加n是为了防止溢出)。

DFS函数实现

void dfs(int u) {
    if (u == n) { // 如果 u == n,说明已经成功放置 n 个皇后,找到一个解
        for (int i = 0; i < n; i++) puts(g[i]); // 输出当前解法
        puts(""); // 输出空行用于分隔
        return; 
    }
    int x = u; // x 代表当前正在处理的行
    for (int y = 0; y < n; y++) { // 枚举当前行的每一列 y
        if (!row[y] && !dg[y - x + n] && !udg[y + x]) { // 如果 y 列、主对角线、副对角线都没有皇后
            g[x][y] = 'Q'; // 在 (x, y) 处放置皇后
            row[y] = dg[y - x + n] = udg[y + x] = true; // 标记列、主对角线、副对角线
            dfs(u + 1); // 递归处理下一行
            g[x][y] = '.'; // 回溯:撤销在 (x, y) 处的皇后
            row[y] = dg[y - x + n] = udg[y + x] = false; // 恢复状态
        }
    }
}

puts函数简介

回溯操作:如果当前行皇后放置成功,继续处理下一行;如果失败,则撤销当前放置的皇后,并尝试下一个位置。通过这种回溯方式,能够找到所有可能的解法。 

主函数

int main() {
    cin >> n; // 读取棋盘大小
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            g[i][j] = '.'; // 初始化棋盘为空位
        }
    }
    dfs(0); // 从第 0 行开始搜索
    return 0;
}
  • 初始化棋盘:将棋盘的每个位置初始化为 '.',表示空位。
  • 调用 dfs(0):从第 0 行开始,尝试放置皇后并找到所有解。

完整代码

#include<bits/stdc++.h>
using namespace std;
const int N=20;
char g[N][N];
bool row[N],dg[N],udg[N];
int n;
void dfs(int u){
    if(u==n)//已经找到一组解
    {
        for(int i=0;i<n;i++) puts(g[i]);
        puts("");
        return;
    }
    //枚举u这一行,搜索合法的列
    int x=u;
    for(int y=0;y<n;y++)
    {
        if(!row[y]&&!dg[y-x+n]&&!udg[y+x]) 
        {
            g[x][y]='Q';
            row[y]=dg[y-x+n]=udg[y+x]=true;
            dfs(u+1);
            g[x][y]='.';
            row[y]=dg[y-x+n]=udg[y+x]=false;
            
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            g[i][j]='.';
        }
        
    }
    dfs(0);
    return 0;
    
}

 

猜你喜欢

转载自blog.csdn.net/qq_73704268/article/details/142706029