【算法模板】dfs 八皇后问题

article/2025/9/15 8:36:00

1.前言

 本文将以经典的八皇后问题来解析dfs的主要思想。

2.题目

题目出处:活动 - AcWing

 3.思路讲解

dfs的思想暗含树的历遍,主要步骤为:

判断是否搜索完毕---历遍寻找符合条件的元素---递归进入下一层搜索---还原现场

 我们可以先分析这个问题,发现皇后在每一行只能有一个,并且对角线,反对角线,每一排,每一列都只有一个皇后。

那么我们就可以从底层出发,遍历一排中的每一个元素,然后深入搜索下一排符合条件的元素,搜索到最后时,即是符合条件的第一个答案,回溯到第一排的下一个元素进行搜索。

由于dfs的灵魂是递归,所以递归的知识一定要掌握清楚。

4.代码实现

 参照以下网格来理解代码:

 

 

 该方法符合dfs的一般做法,当然算法是死的,人是活的,依照不同的题目,dfs的参数,形式等多种多样,不敢一板子把代码论死。要参照思想,具体情况具体分析,dfs最重要的便是顺序!!!

4.1 法1

#include <iostream>
using namespace std;
const int N = 20;//定义图(网格)
char path[N][N];//col记录每一列的皇后数,确保只有1个
//dg记录正对角线的皇后数,确保只有1个
//udg记录反对角线的皇后数,确保只有1个
bool col[N],dg[N],udg[N];//网格数n
int n;void dfs(int u)
{//搜索完毕,并且符合要求时打印if(u==n){for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){cout<<path[i][j];}cout<<endl;}cout<<endl;return;}//y代表y轴上的点for(int y = 0; y < n; y++){//如果一列里面没有元素,对角线上没有元素,那么放入皇后Q;if(!col[y]&&!dg[y+u]&&!udg[y-u+n]){path[u][y]='Q';col[y]=dg[y+u]=udg[y-u+n]=true;//皇后数+1,进入下一层搜索dfs(u+1);//回溯到原始状态col[y]=dg[y+u]=udg[y-u+n]=false;path[u][y]='.';}}}int main()
{cin>>n;//先初始化网格,再由dfs确定皇后位置for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){path[i][j]='.';}}//从第0层开始(初始皇后数为0)dfs(0);return 0;
}

这里解释一下对角线的判定:

由直线方程y=(±)x+b;

我们想要一条对角线上的皇后只有一个,而一条直线上,截距是一样的,b = y ± x ;

但是由于数组的下标没有负数, y - x 有可能是负数,所以加上n,映射成正数!

如果(u)dg[ b ] 为真,那么该直线上已经有一个皇后。

4.2 法2

 

#include <iostream>
using namespace std;
const int N = 20;
char path[N][N];
//判断行,列,对角线
bool row[N],col[N],dg[N],udg[N];
int n;void dfs(int x,int y,int s)
{//初始化条件if(y == n){x++;y = 0;}if(x == n){//搜素完毕,并且符合要求的条件if(s==n){for(int i = 0; i < n; i++){puts(path[i]);}puts(" ");}return;}//初始化网格path[x][y]='.';dfs(x,y+1,s);//思路同法1if(!row[y]&&!col[x]&&!dg[x+y]&&!udg[y-x+n]){row[y]=col[x]=dg[x+y]=udg[y-x+n]=true;path[x][y]='Q';dfs(x,y+1,s+1);row[y]=col[x]=dg[x+y]=udg[y-x+n]=false;path[x][y]='.';        }}
int main()
{cin>>n;dfs(0,0,0);return 0;
}

但是法2在效率上远不如法1,因为在初始化回溯时进行搜索,浪费了很多不必要的搜索,只有当x,y回溯到0时才真正起到作用。

举此法是为了说明dfs的灵活性。

5.结语

 作为图论的必备入门技巧,要把握dfs的思想,并且熟练运用。

其实dfs更像一种循环,在if条件下找到不同层数的答案,完成搜索后继续下一个搜索,在不影响原来的数据的情况下输出答案。

后续会更新bfs的有关内容。


http://chatgpt.dhexx.cn/article/UBgwyk8W.shtml

相关文章

八皇后递归算法

八皇后问题 &#xff1a;假设 將八个皇后放到国际象棋盘上&#xff0c;使其两两之间无法相互攻击。共有几种摆法&#xff1f; 基础知识&#xff1a; 国际象棋里&#xff0c;棋盘为8X8格。 皇后每步可以沿直线、斜线 走任意格。 思路&#xff1a; 1.想把8个皇后放进去&…

算法设计(一) : 搜索算法实现八皇后问题

写在开头&#xff1a;实验结果截图8皇后太多截不完&#xff0c;用4皇后代替了&#xff0c;只需将n->8就行 目录 写在开头&#xff1a;实验结果截图8皇后太多截不完&#xff0c;用4皇后代替了&#xff0c;只需将n->8就行图解算法过程&#xff1a;算法一&#xff1a;DFS 按…

八皇后问题(递归回溯算法详解+C代码)

为了理解“递归回溯”的思想&#xff0c;我们不妨先将4位皇后打入冷宫&#xff0c;留下剩下的4位安排进4x4的格子中且不能互相打架&#xff0c;有多少种安排方法呢&#xff1f;现在我们把第一个皇后放在第一个格子&#xff0c;被涂黑的地方是不能放皇后的&#xff1a; 第二行的…

算法设计与分析——八皇后问题的实现——代码分析和讲解

文章目录 题目描述思路分析回顾回溯法的基本框架解题框架应用到本题定义问题的解空间定义约束函数模仿回溯法的框架去解决问题 实现源码分析与总结 题目描述 在88格的棋盘上放置彼此不受攻击的8个皇后。国际象棋的规则&#xff1a;皇后可以攻击与之处在同一行或同一列或同一斜…

八皇后问题算法(C语言实现)

1. 八皇后的由来和问题 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一…

八皇后算法解析

今天研究力扣的一道题死活写不出来对应的算法&#xff0c;没办法自己算法基础太差。于是看了下答案&#xff0c;发现使用什么回溯算法&#xff0c;菜鸟表示平时开发期间写的最复杂的程序就是写了两层for循环&#xff0c;已经很牛逼了有木有&#xff1f;这个回溯算法什么鬼&…

递归算法之八皇后问题

八皇后问题&#xff08;英文&#xff1a;Eight queens&#xff09;&#xff0c;是由国际象棋棋手马克斯贝瑟尔于1848年提出的问题&#xff0c;是回溯算法的典型案例。 问题表述为&#xff1a;在88格的国际象棋上摆放8个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个…

八皇后问题4种c语言算法

八皇后问题 1.递归回溯法 B站懒猫老师讲的&#xff08;我在这里学的&#xff09; 八皇后问题的递归回溯算法思路&#xff1a;从第一行开始当某一行皇后位置不与前面所有皇后位置冲突那么记录该行皇后位置并调用递归函数进入下一行&#xff0c;摆放下一个皇后&#xff0c;逐个…

数据结构与算法 — 八皇后问题(回溯算法)

问题描述 在88格的国际象棋上摆放8个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上&#xff0c;问有多少种摆法。 假设上图中红点为一个皇后的位置&#xff0c;那么他的同行&#xff0c;列&#xff0c;斜线上都不能再放置…

数据结构与算法-- 八皇后问题(多种实现方案)

八皇后问题解法一(排列筛选法) 本篇我们承接上一篇中的思想&#xff0c;想到了一个经典的算法题&#xff0c;八皇后问题&#xff1a;题目&#xff1a;在8*8的国际象棋上摆放8个皇后&#xff0c;使得其互相不能攻击&#xff0c;即任意两个换后不能在同一行&#xff0c;同一列&a…

C语言开方问题求助

求助&#xff1a; 使用的是Devcpp进行的编程尝试 在写程序的时候遇到了个问题&#xff0c;运行后结果显示为1#j 后来在朋友的帮助下改正了程序&#xff0c;解决了错误。之后的话&#xff0c;我按照我朋友的改正过的程序自己再重新打了一遍&#xff0c;结果运行后的结果还是显示…

C语言笔记

目录 基础... 3 基本类型数据... 5 定义变量... 6 进制... 6 ASCII&#xff08;阿斯克码&#xff09;... 7 输入输出... 8 printf&#xff08;&#xff09;将变量的内容输出到显示器上... 8 scanf &#xff08;&#xff09;[通过键盘将数据输入到变量中] 9 运算符... …

c语言 大数开方,大数加法之C语言函数法(只有正数版)

由于某些原因&#xff0c;我于今天2017-4-19将我的博文搬到博客园了&#xff0c;以后我就在这里扎根了。 之前想过在博客写文章方便日后复习&#xff0c;但一直未能实现&#xff0c;所以&#xff0c;现在这篇是我个人人生中第一篇博客&#xff0c;所以写博客完全没经验&#xf…

开平方的快速算法(C代码)

目录&#xff1a; 一、牛顿迭代法 二、采用移位、加减法、判断和循环实现开平方 三、效率远高于牛顿迭代法开平方法 1、原理 2、实现代码 四、卡马克快速开平方算法(推荐) 1、C-Free模拟验证卡马克开平方 2、移植到实际的项目 3、卡马克快速开平方的由来 1&#xff0…

windows 区域截屏以及延迟截屏

提起在Windows&#xff0c; 我们都会用到截屏功能&#xff0c;今天论述一下window 10系统自带的截图应用Snipping Tool 打开Snipping Tool 找到任务栏下的放大镜图标&#xff0c;点击 在下方输入snipping&#xff0c;会在左侧找到截图软件Snipping Tool&#xff0c;点击可进入…

小米手机解决此区域不可截屏

小米手机解决此区域不可截屏 无意中暂停视频弹出消息&#xff0c;想试试可不可以截屏竟然可以截屏&#xff0c;但是视频一播放就截屏不了了&#xff0c;录屏也是&#xff0c;直接变黑或者是直接提示弹窗&#xff0c;嘻嘻嘻嘻小米bug还是有好处滴

浏览器网页截屏实用小技巧

浏览器开发者工具中自带的截屏太方便了&#xff01; 打开开发者工具&#xff0c;输入 ctrl shift P 快捷键&#xff0c;输入screenshot&#xff0c;出现了四个选项&#xff0c;分别是&#xff1a; 1.area screenshot - 区域截图 2.full size screenshot - 对浏览器所有内容…

如何利用计算机截屏快捷键,电脑怎么截图 电脑选区域截图怎么截 电脑截图快捷键是什么...

电脑怎么截图 按照操作上从易到难的顺序&#xff0c;给你推荐五种截屏方式 &#xff1a; 第一种&#xff1a;Ctrl PrScrn 使用这个组合键截屏&#xff0c;获得的是整个屏幕的图片; 第二种&#xff1a;Alt PrScrn 这个组合键截屏&#xff0c;获得的结果是 当前窗口的图片; 第三…

iOS 截屏指定区域

转自&#xff1a;链接&#xff1a;https://www.jianshu.com/p/39db0fa66c0e 指定截屏代码实现 全屏截图效果 全屏截图效果 指定区域截屏效果 指定区域截屏效果 这里先上代码&#xff0c;代码后面有相关方法的解释第一种方法代码下载 /**创建一个基于位图的上下文&#xff0…

windows如何截屏

截屏是我们平时工作或记录常用的操作&#xff0c;不过有人不知道怎么用系统截屏&#xff0c;今天&#xff0c;小编带来了系统的几种截屏&#xff0c;让我们来看看吧&#xff01; 一、快捷键截图 1. Win shift S&#xff1a;可以选择截图区域的大小&#xff0c;CtrlV粘贴在w…