n-皇后问题【所用算法——dfs】

n-皇后问题是指将 n 个皇后放在 n∗n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
在这里插入图片描述
现在给定整数n,请你输出所有的满足条件的棋子摆法。

输入格式
共一行,包含整数n。

输出格式
每个解决方案占n行,每行输出一个长度为n的字符串,用来表示完整的棋盘状态。

其中”.”表示某一个位置的方格状态为空,”Q”表示某一个位置的方格上摆着皇后。

每个方案输出完成后,输出一个空行。

输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围
1≤n≤9
输入样例:
4
输出样例:
.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…


这一道题是dfs的应用,算是中等难度的题目了,现在先给出我的代码,然后再给出我的解释

#include <cstring>
#include <iostream>

using namespace std;

const int N = 20;

int n;
char g[N][N];//读入图
bool col[N], dg[N], udg[N];//col表示列,dg正斜线,udg反斜线

void dfs(int u){
    if (u == n){//当进行到n的时候,输出数据
        for (int i = 0; i < n; i ++ ) puts(g[i]);//输出一行的字符串
        puts("");//换行操作
        return;
    }
    
    for(int i = 0; i < n; i ++ )//i表示列
        if (!col[i] && !dg[n + u - i] && !udg[u + i]){
            //值为0表示当前位置不管是横着、竖着、斜着都没人,那就可以填上一个皇后
            g[u][i] = 'Q';//给这个位置安上一个皇后
            col[i] = dg[n + u - i] = udg[u + i] = true;//这个位置所在的行列斜线都被占了
            dfs(u + 1);//进行下一行
            g[u][i] = '.';//还原
            col[i] = dg[n + u - i] = udg[u + i] = false;//还原
        }
}

int main(){
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';//开始的时候,每个位置都没有皇后
            
    dfs(0);//还是dfs
    
    return 0;
}

在国际象棋中,皇后有很大的本事,可以沿着横线走,也可以沿着斜线走,所以基于这一点,我们要在一个n*n的棋盘上放置n个皇后,一定不能让他们在同一行,同一列,同一斜线上,不然那还不得打起来。

对于这一题,我们应当使dfs算法是毋庸置疑的,那我们就来聊一聊该怎么使用dfs

我们知道dfs是深度优先遍历,它可以将所有的方法都给试一遍,这也就解决了题目中要求我们将所有的方案都给输出的问题。

先来介绍 一下全局变量里面开的数组
在这里插入图片描述
其他的地方没什么好说的,我们直接来说一下dfs函数内部的情况吧。

dfs内部只有一个要解释的,就是怎么判断某个位置所在的行、列、以及正反斜线上没有其他的皇后。
这个时候,我们进行判断就需要我们之前在全局变量里面定义的bool数组了。

col这个数组很好解释,col[i] == false就表示第i行这一行里没有皇后。
那dg这个数组表示正斜线,那dg[n+u-i]是怎么来的呢
请看下图
在这里插入图片描述
udg这个数组表示反斜线,udg[u + i}是怎么得到的呢,我们再来看一下。
在这里插入图片描述

到这里,所有问题都给解决了,如果对dfs内部运行不太了解,可以看一下我的上一篇题解
全排列问题 <–点击这里

如果感觉有用,点个赞再走吧,给我持续用爱发电的动力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值