深度优先搜索的例子以及分析

1. 问题描述:

深度优先搜索特别适用于那些探索所有的可能性的这些问题,问题解决的可能性是非常多的,所以需要去探索所有的可能性,从而找到所有能够满足问题的解决方案或者是解决方案中最优的那一个,下面是使用深度优先搜索比较经典的例子

2. 具体的例子如下:

① 比如数独游戏,走迷宫这些都是可以使用深度优先搜索来进行解决,数独游戏中尝试着往格子里面填入1-9的数字,每一个格子都是这样去尝试,最终可以得到完整的填满数字的数独,而迷宫问题则是对于当前这个位置我尝试着去走,假如这条路走不通,那么我换一条别的路径看一下能否走得通,这也体现了深度优先搜索的特点,先纵后横,一条路走到黑,走不通退回来走其他的路径

深度优先搜索经常要结合回溯来进行使用,为什么需要进行回溯呢?原因是当前我尝试这种的可能的方案,但是我需要尝试另外一种方案,这个时候就需要将之前已经填过的数字清除,这样在尝试其他的状态(下一次的递归调用)的时候才不会受到上一次递归调用的影响,所以回溯通常是递归调用的时候上一次对下一次调用的时候有影响的时候我们需要清除一下之前的状态

② 八皇后问题,深度优先典型的例子,每一个行的每一个位置我都尝试去放置皇后,假如不行那放到当前行其他位置,当无论如何当前行都不能够放置那么我们退回到上一次放置的地方,尝试在上一次的那一行将皇后放置在其他的位置这样去尝试所有的可能性

③ 全排列的递归加上回溯框架的求解,将当前位置与当前位置以及以后的位置上的元素进行互换,因为第一次的时候下标为1的这个位置与1以及其他的位置进行交换,所以当下标为2的时候时候那么只需要与2以及以后以后的位置进行交换,因为在下标为1的时候已经与2进行了交换,这个时候不需要再将下表为2的元素与下标为1的元素进行交换,其他的元素也是一样的,所以需要使用递归来进行求解,在for循环中嵌套递归

④ 部分和,给出的n个数字中找到m和数字加起来等于sum,对于当前的元素我可以选择要,使其参与到构成目标sum的元素中,也可以选择不要,这样就形成了两个平行状态,类似于一棵二叉树的搜索,分别递归左子树与右子树,将当前节点分为左右节点去求解,所以也是在尝试每一种的可能性,最终可以得到若干个能够加起来的和等于目标sum的数字序列

检验连通性的问题,例如八联通检测与死联通检测的问题,深度优先也别适合于这类检验连通性问题的求解,因为dfs会把所有连在一起的元素在一次的递归调用都会连接到,所以特别适合于解决这类问题,还有就是水洼的数量的例子也是类似的检验连通性的问题

通常在搜索的时候将数组中的元素变为相反的元素,在水洼的数目的例子中使用这个就是一个套路,每调用dfs就将水洼变成了干燥的块:

for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++){
		//有'W'的地方说明有积水
	        if(arr[i][j] == 'W'){
		        dfs(arr, i, j);
			    count++;
		    }    
		}
}

    private static void dfs(char[][] arr, int i, int j) {
		arr[i][j] = '.';
		for(int k = -1; k <= 1; k++){
			for(int l = -1; l <= 1; l++){
				if(k == 0 && l == 0) continue;
				if(i + k >=0 && j + l<= arr[0].length - 1 && i + k <= arr.length - 1 && j + l >=0){
					if(arr[i + k][j + l] == 'W'){
						//继续搜寻它的下一个积水
						dfs(arr, i + k, j + l);
					}
				}
			}
		}	
	}

树和图的遍历,特别是在对树的节点的操作中,经常要使用到dfs,中序遍历。前序遍历,后序遍历这些都要使用到递归来求解,求解某个节点的高度等等这些问题,还有就是在图的遍历中也是如此,一个节点可以通过dfs连到另外一个与之相连的节点

3. 可以看到几乎所有尝试可能性的问题都可以使用dfs来解决

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值