【总结】DFS 模板套路及例题详解


以下内容收集了全网以及整合了自己写的部分。


深度优先搜索

  • 深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。

  • 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。

  • 整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

  • 思想:一直往深处走,直到找到解或者走不下去后回溯。

  • DFS和BFS的区别: 深搜和广搜在实现上分别用的是栈(栈和函数递归本质是一样)和队列。一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(好比3步就必需达到前提)"的标题,它的空间效率高,然则找到的不必定是最优解,必需记实并完成全数搜索,故一般情况下,深搜需要很是高效的剪枝(优化).



DFS 模板套路

简单版
在这里插入图片描述

详细版

//模板1
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int map[maxn][maxn]; // 坐标范围
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向

bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
	if(!vst[x][y] && ...) // 满足条件
		return 1;
	else // 与约束条件冲突
		return 0;
}

void dfs(int x,int y)
{
	vst[x][y]=1; // 标记该节点被访问过
	if(map[x][y]==G){ // 出现目标态G
		...... // 做相应处理
		return;
	}
	for(int i=0;i<4;i++){
		if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点
			dfs(x+dir[i][0],y+dir[i][1]);
	}
	return; // 没有下层搜索节点,回溯
}

int main()
{
	......
	return 0;
}


//模板2
void dfs()//参数用来表示状态  
{  
    if(到达终点状态){  
        ...//根据题意添加  
        return;  
    }  
    if(越界或者是不合法状态)  
        return;  
    if(特殊状态)//剪枝
        return ;
    for(扩展方式){  
        if(扩展方式所达到状态合法){  
            修改操作;//根据题意来添加  
            标记;  
            dfs();  
            (还原标记)//是否还原标记根据题意  
            //如果加上(还原标记)就是 回溯法  
        }  
 
    }  
}  


DFS 经典题目

题解: DFS 经典题目详解



还不够熟练?那就再训练以下题目

【kuangbin 带你飞】专题一 简单搜索 题解

### 关于DFS算法的C++实现及其详细解释 #### 一、DFS算法简介 深度优先搜索(Depth First Search, DFS)是一种用于遍历或搜索树或图的算法。该算法会尽可能深地探索每一个分支,直到无法继续为止,再回溯到上一个节点并重复此过程。 #### 二、DFS算法的特点 - **节省空间**:DFS利用栈来记录访问路径上的节点信息,在大多数情况下仅需保持一条从根结点至当前处理中的叶结点之间的链路,从而减少了所需的空间开销[^1]。 - **易于编码**:相较于其他类型的搜索方法而言,采用递归方式编写的DFS程序逻辑清晰明了,便于初学者掌握和应用;当然也可以通过显式维护堆栈来进行迭代式的非递归版本开发,后者可能带来性能优势但在可读性方面稍逊一筹[^3]。 #### 三、基于递归的DFS函数定义 下面给出了一种典型的递归形式下的DFS模板: ```cpp void dfs(int node) { visited[node] = true; // 将当前顶点标记为已访问 cout << "Visit Node:" << node << endl; for (auto neighbor : adjList[node]) { // 遍历邻接表中与node相连的所有邻居nodes if (!visited[neighbor]) // 如果某个邻居还没有被访问过,则对其执行dfs操作 dfs(neighbor); } } ``` 这里`adjList[]`表示图结构的一种常用表达——邻接列表,而布尔数组`visited[]`用来跟踪哪些顶点已经被探查过了以防止无限循环的发生。 #### 四、初始化工作 为了能够顺利运行上述核心部分之前还需要做一些准备工作,比如创建好输入数据对应的图形描述以及重置状态变量等: ```cpp int main() { int n,m; cin >> n >> m ;// 输入n个点m条边组成的无向图 vector<vector<int>> adjList(n+1); // 初始化大小为n+1的二维vector作为邻接矩阵 vector<bool> visited(n+1,false); // 同样长度的状态标志位,默认全部设成false即未访问状态 while(m--) { int u,v; cin >> u >> v ; adjList[u].push_back(v); // 添加双向连接关系 adjList[v].push_back(u); } dfs(startNode); // 对指定起点调用dfs进行深入探寻 } ``` 以上就是有关DFS算法在C++环境里的具体实践指南[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值