DFS深度优先搜索-程序员宅基地

技术标签: 算法  深度优先  c++  AcWing算法基础(C++代码)  


一、DFS的概念

DFS的定义

DFS(Depth-First Search)深度优先搜索,是一种常用的图遍历算法,用于在图或树数据结构中遍历所有节点。

DFS的搜索方式

DFS
 DFS的搜索

深度优先搜索从一个起始节点开始,沿着一条路径尽可能远地访问节点,直到到达不能继续前进的节点,然后返回上一层继续探索其他路径。这个过程是递归的,通过不断地深入进入节点的子节点,直到遍历完整个图。

DFS采用的数据结构

深度优先搜索使用栈(Stack)数据结构来保存需要探索的节点。每次访问一个节点时,将其标记为已访问,并将其未访问的邻居节点压入栈中。然后从栈中弹出一个节点,继续访问该节点的未访问邻居节点,直到栈为空。

空间复杂度: O ( n ) O(n) O(n)

DFS的特点

DFS不保证找到最短路径。因为它首先沿着一条路径尽可能远地深入。如果需要找到最短路径,可以考虑使用其他算法,如广度优先搜索(BFS)或 Dijkstra 算法。一般最小步数、最短距离、最小操作次数等问题采用BFS。思路奇怪或是对空间要求高的使用深度优先搜索(DFS)。

DFS 在解决许多图论问题和遍历问题上非常有用,如查找图中的路径、连通性检测、拓扑排序等。它也可以应用于树的遍历,例如先序遍历、中序遍历和后序遍历。


二、DFS的实战应用

1.排列数字

题目描述:
给定一个整数 n n n,将数字 1 ∼ n 1∼n 1n 排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

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

输出格式:
按字典序输出所有排列方案,每个方案占一行。

数据范围:
1 ≤ n ≤ 7 1≤n≤7 1n7

输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

实现思路
实现思路


代码实现:
1.使用bool类型数组来表示是否占用

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

const int N = 10;
int n, path[N];
bool st[N]; // 状态数组

void dfs(int u) // 第几个数字,一共几个数字
{
    
    if (u == n)// 递归到最后一个数字
    {
    
        for (int i = 0; i < n; i++) cout << path[i] << ' '; // 输出保存的结果
        puts(" ");
    }

    for (int i = 1; i <= n; i++)
        if (!st[i]) // 没有被用过的数
        {
    
            path[u] = i;
            st[i] = true; // i被用过
            dfs(u + 1);// 走到下一层
            st[i] = false;// 恢复现场
        }
}
int main()
{
    
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin >> n;
	dfs(0);
	return 0;
}

2.使用整型变量补码的每位来表示是否占用

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

const int N = 10;
int n, path[N];

void dfs(int u, int state) // 第几个数字,一共几个数字
{
    
    if (u == n)// 递归到最后一个数字
    {
    
        for (int i = 0; i < n; i++) cout << path[i] << ' '; // 输出保存的结果
        puts(" ");
    }

    for (int i = 0; i < n; i++)
        if (!(state >> i & 1)) // 没有被用过的数
        {
    
            path[u] = i + 1;
            dfs(u + 1, state + (1 << i));
        }
}
int main()
{
    
	cin.tie(0);
	ios::sync_with_stdio(false);
	cin >> n;
	dfs(0, 0);
	return 0;
}

2.n-皇后问题

题目描述:
n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

国际象棋棋盘
现在给定整数 n n n,请你输出所有的满足条件的棋子摆法。

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

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

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

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

注意:行末不能有多余空格。

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

数据范围:
1 ≤ n ≤ 9 1≤n≤9 1n9

输入样例:

4

输出样例:

.Q..
...Q
Q...
..Q.

..Q.
Q...
...Q
.Q..

代码实现:

//在此处,为了模拟坐标轴,使用u替换y,使用i替换x
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
const int N=20;//此处x轴和y轴的长度为10,开20是大了,但是对角线长度约1.414*10(根号2),所以数组开大有好处
int n;//此处存储输入的行数&列数,
char q[N][N];//构建棋盘,大一些没坏处,注意类型需要为char(一开始无语写了个int)
bool col[N],dg[N],udg[N];//col是Column(列)的缩写,dg是diagonal(对角)的缩写,(反对角线前面的u想不出了)
//设udg的方程为y=x+b则b=y-x,替换后b=u-i,防止出现负数,则加上n,则有b=u+n-i(其实b=n+i-u也可,目的是一个对角线能单独映射)
//设dg的方程为y=-x+b,b=y+x,替换后b=i+u,perfect
void dfs(int u){
    //已经操作了u行
    if(u==n){
    //好家伙,已经操作完u行了,一个输出了
        for(int i=0;i<n;i++){
    
            cout<<q[i]<<endl;
        }
        cout<<endl;
        /*这种写法也可,但是如果上面的看不懂建议补习C语言基础
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout<<q[i][j];
            }
            cout<<endl;
        }
        cout<<endl;
        */
        return;
    }
    for(int i=0;i<n;i++){
    //到这一步说明还没有dfs搜索完
        if(!col[i] and !dg[i+u] and !udg[u+n-i]){
    //这个点在各种映射下都是合法的
            q[u][i]='Q';
            col[i]=dg[i+u]=udg[u+n-i]=true;//这些点用掉啦
            dfs(u+1);//继续往下一层探
            q[u][i]='.';
            col[i]=dg[i+u]=udg[u+n-i]=false;//出来后这些点恢复原状
        }
    }
}
int main(){
    
    cin>>n;//输入行数
    for(int i=0;i<n;i++){
    //搭建一个“船新”的棋盘
            for(int j=0;j<n;j++){
    
                q[i][j]='.';
            }
        }
    dfs(0);//0代表目前已经操作了0行,并且需要对第1行进行操作(在数组中映射为0行)
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq947467490/article/details/131440117

智能推荐

计算机丢失concrt140,小编教你解决concrt140 dll 【解决教程】 的技巧_-程序员宅基地

文章浏览阅读4.5w次。近日有小伙伴发现电脑出现问题了,在突然遇到concrt140 dll时不知所措了,对于concrt140 dll带来的问题,其实很好解决concrt140 dll带来的问题,下面小编跟大家介绍concrt140 dll解决方法:丢失CONCRT140.dll,怎么办?答:分析及解决:网上下载这个DLL文件,将其放置到system32目录下面。 重启系统,或者在CMD下面运行regsvr32*.dl..._concrt140.dll下载教程

微信小程序源码案例大全_微信小程序switch页面demo-程序员宅基地

文章浏览阅读4.3k次,点赞4次,收藏62次。微信小程序demo:足球,赛事分析 小程序简易导航 小程序demo:办公审批 小程序Demo:电魔方 小程序demo:借阅伴侣 微信小程序demo:投票 微信小程序demo:健康生活 小程序demo:文章列表demo 微商城(含微信小程序)完整源码+配置指南 微信小程序Demo:一个简单的工作系统 微信小程序Demo:用于聚会的小程序 微信小程序Demo:Growth 是一款..._微信小程序switch页面demo

SLAM学习笔记(Code2)----刚体运动、Eigen库_eigen.determinant-程序员宅基地

文章浏览阅读2.2k次。2.1除了#include<iostream>之外的头文件#include <Eigen/Core>//Core:核心#include <Eigen/Dense>//求矩阵的逆、特征值、行列式等#include <Eigen/Geometry>//Eigen的几何模块,可以利用矩阵完成如旋转、平移/***其他***/#include <ctime>//可用于计时,比较哪个程序更快#include <cmath>//包含a_eigen.determinant

图像梯度-sobel算子-程序员宅基地

文章浏览阅读1w次,点赞12次,收藏61次。(1)理论部分x 水平方向的梯度, 其实也就是右边 - 左边,有的权重为1,有的为2 。若是计算出来的值很大 说明是一个边界 。y 竖直方向的梯度,其实也就是下面减上面,权重1,或2 。若是计算出来的值很大 说明是一个边界 。图像的梯度为:有时简化为:即:(2)程序部分函数:Sobelddepth 通常取 -1,但是会导致结果溢出,检测不出边缘,故使..._sobel算子

cuda10.1和cudnn7.6.5百度网盘下载链接(Linux版)_cudnn7.6网盘下载-程序员宅基地

文章浏览阅读3.6k次,点赞17次,收藏8次。cuda10.1和cudnn7.6.5百度网盘下载链接(Linux版)在官网下载不仅慢,,,主要是还总失败。。终于下载成功了,这里给出百度网盘下载链接,希望可以帮到别人百度网盘下载链接提取码: vyg5_cudnn7.6网盘下载

Python正则表达式大全-程序员宅基地

文章浏览阅读9.3w次,点赞69次,收藏427次。定义:正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。上面都是官方的说明,我自己的理解是(仅供参考):通过事先规定好一些特殊字符的匹配规则,然后利用这些字符进行组合来匹配各种复杂的字符串场景。比如现在的爬虫和数据分析,字符串校验等等都需要用_python正则表达式

随便推点

NILM(非侵入式电力负荷监测)学习笔记 —— 准备工作(一)配置环境NILMTK Toolkit_nilmtk学习-程序员宅基地

文章浏览阅读1.9w次,点赞27次,收藏122次。安装Anaconda,Python,pycharm我另一篇文章里面有介绍https://blog.csdn.net/wwb1990/article/details/103883775安装NILMTK有了上面的环境,接下来进入正题。NILMTK官网:http://nilmtk.github.io/因为官方安装流程是基于linux的(官方安装流程),我这里提供windows..._nilmtk学习

k8s-pod 控制器-程序员宅基地

文章浏览阅读826次,点赞20次,收藏28次。如果实际 Pod 数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当 Pod 失败、被删除或者挂掉后,RC 都会去自动创建新的 Pod 来保证副本数量,所以即使只有一个 Pod,我们也应该使用 RC 来管理我们的 Pod。label 与 selector 配合,可以实现对象的“关联”,“Pod 控制器” 与 Pod 是相关联的 —— “Pod 控制器”依赖于 Pod,可以给 Pod 设置 label,然后给“控制器”设置对应的 selector,这就实现了对象的关联。

相关工具设置-程序员宅基地

文章浏览阅读57次。1. ultraEdit设置禁止自动更新: 菜单栏:高级->配置->应用程序布局->其他 取消勾选“自动检查更新”2.xshell 传输文件中设置编码,防止乱码: 文件 -- 属性 -- 选项 -- 连接 -- 使用UTF-8编码3.乱码修改:修改tomcat下配置中,修改: <Connector connectionTimeou..._高级-配置-应用程序布局

ico引入方法_arco的ico怎么导入-程序员宅基地

文章浏览阅读1.2k次。打开下面的网站后,挑选要使用的,https://icomoon.io/app/#/select/image下载后 解压 ,先把fonts里面的文件复制到项目fonts文件夹中去,然后打开其中的style.css文件找到类似下面的代码@font-face {font-family: ‘icomoon’;src: url(’…/fonts/icomoon.eot?r069d6’);s..._arco的ico怎么导入

Microsoft Visual Studio 2010(VS2010)正式版 CDKEY_visual_studio_2010_professional key-程序员宅基地

文章浏览阅读1.9k次。Microsoft Visual Studio 2010(VS2010)正式版 CDKEY / SN:YCFHQ-9DWCY-DKV88-T2TMH-G7BHP企业版、旗舰版都适用推荐直接下载电驴资源的vs旗舰版然后安装,好用方便且省时!) MSDN VS2010 Ultimate 简体中文正式旗舰版破解版下载(附序列号) visual studio 2010正_visual_studio_2010_professional key

互联网医疗的定义及架构-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏17次。导读:互联网医疗是指综合利用大数据、云计算等信息技术使得传统医疗产业与互联网、物联网、人工智能等技术应用紧密集合,形成诊前咨询、诊中诊疗、诊后康复保健、慢性病管理、健康预防等大健康生态深度..._线上医疗的定义