深度优先搜索小结

深度优先搜索(DFS)在解决组合问题中起到关键作用,通过模拟走迷宫的过程,避免重复路径。例如,从给定数字集合中找出和为特定值的组合,可以利用DFS进行状态转移,降低复杂度。DFS在实际应用中需要剪枝优化,如图结构的遍历问题,通过一次DFS遍历相连的元素,达到高效求解的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深度优先搜索(DFS)

深度优先搜索就好比走迷宫, 不断顺着一条路走, 直到走不通为止, 然后回退到上一个路口再向另外的方向行走(走过的方向就不会再走了,又不是傻子, 知道走不通,还向走不通的方向走), 不断重复(试过所有路口, 状态转移), 重复直到找到唯一的一条合适的路径;
DFS可以看做是二叉树的先序遍历, 多说无益; 直接上题;

例1:
给定a1, a2, a3,…an个数, 从中选出若干个数, 使他们的和恰好为K
输入: n=4; a={1,2,4,7}; K=13;
输出: 2+4+7=13
分析: 当初我看到这道题, 就是懵逼状态, 唉, DFS还没搞清楚就开始做题, 很蠢, 不扯那些没用的, 回归主题: 从给出的例子来看, 既然我们要从1,2,4,7中选出若干个数, 那就可以暴力枚举, 循环列举出a集合的幂集, 找出满足条件的答案; 但是这种方法的复杂度让我瘆得慌, 复杂度为O(n^n), so, 这种做法就果断放弃, 从今天的主题来看势必要用到DFS来解决问题(我这不废话吗, 唉), 从DFS的定义来看就是状态转移, 这里的状态转移表示的是每个数都拥有两个选择的权利, 要么加, 要么不加, 就好比走迷宫有两条路, 要么朝左, 要么朝右, 你把这个过程想象走迷宫, 每种选择都对应着不同的走法, 总有一条路是对的(看成一棵长得像二叉树一样的迷宫), 因此复杂度为2的n次方, 相比前面的n的n次方下降了很多, 尽管下降了很多但是在实际应用需要做剪枝优化, 就题论事有如下代码:

#include<iostream>
using namespace std;
int n=4,a[4]={1,2,4,7},k=13;
bool dfs(int i,int sum){
	if(i==n)return sum==k;//满足条件然后进行回归
	if(dfs(i+1,sum)) {//在交叉口做选择
//		cout<<" "<<a[i]<<endl;
//	如果没加就不用输出a[i],忽略了这个问题 
		return true;
	}
	if(dfs(i+1,sum+a[i])){
		cout<<" "<<a[i]<<endl;
		return true;
	}
	return false;
}
int main(){
	cout<<dfs(0,0)<<endl;
	return 0;
} 

上述整个过程可看做二叉树的前序遍历, 当满足条件便回归
深度优化搜索总是从最开始的状态出发,遍历所有可能到达的状态, 由此可对所有产生的状态进行操作

例2:
在这里插入图片描述
这道题是深度优化搜索的一个很好例子, 拿来作为参考
分析: 以第一个题作为启示, 第一个题可看做单连通域进行遍历, 总共只在main函数中使用了一次dfs, 而这道题当遇到积水时就需要使用dfs, 一次dfs就能对相连的’w’进行遍历,直到一个连通域遍历完成, 如图总共有3个连通域, 多说无益看代码:

#include<iostream>
using namespace std;
int N=10,M=12;
char field[10][12]={
	"w.......ww.",
	".www....ww.",
	"...w.....w.",
	".........w.",
	".........w.",
	"wwww.....ww",
	"www.......w",
	"ww........w",
	"ww........w",
	"w.........."};
void dfs(int x,int y){
	field[x][y]='.';
	for(int dx=-1;dx<=1;dx++){
		for(int dy=-1;dy<=1;dy++){//针对当前'w'的8个方向使用dfs, 直到一个连通域遍历完成
			int nx=x+dx,ny=y+dy;
			if(0<=nx&&nx<N&&0<=ny&&ny<M&&field[nx][ny]=='w')//满足条件开始遍历
				dfs(nx,ny);
		}
	}
	return;
} 
int main(){
	int res=0;
	for(int i=0;i<N;i++){
		for(int j=0;j<M;j++){
			if(field[i][j]=='w'){//针对整个地图使用dfs
				dfs(i,j);
				++res;
			}
		}
	}
	cout<<res<<endl;
}

每个格子至多被调用一次, 所以复杂度O(N*M)
总的来说, 深度优化搜索就是对图结构进行遍历(以二叉树的前序遍历的方式), 直到遇到符合条件的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值