DFS的个人理解和测试例题

深度优先搜索(DFS):

        是一种搜索手段。可以理解为:它从某个位置(起点)开始,沿着一条路不断地向前走直到尽头,然后退后一步,去走其它没走过的路,没有的话,再退后一步,再去选择,直到找到目的地(终点)。

例如下图:

从A(起点)开始走,先走ABD

在D处发现没有子节点,推后到节点B,去走EG

到节点G发现又到了尽头,然后退一步到节点E,发现节点E没有右节点

再退到节点B,发现B的左右节点都走过了,再退到节点A,去走AC

节点C没有左子树,走右子树F,F是尽头,退到C,退到A,返回。


适用场景:

有三个方面,分别是输入数据、状态转换图、求解目标;

输入数据:如果是递归数据结构,如单链表,二叉树,集合,则百分之百可以使用深搜;如果是非递归数据结构,比如一维数组、二维数组、字符串、图,则概率要小一些;

状态转换图:树或者图;

输入数据:必须要走到最深(比如对于树,必须要走到叶子结点)才能得到一个解,这种情况比较适合用深搜;


例题1:

给定整数a1,a2.....an,判断是否可以从中选出若干数,使他们的和恰好为k。

(限制条件:1<=n<=20,-108<=108,-108<=k<=108


简单的DFS运用,每个数据都用两种选择:加上或者不加,时间复杂度:2n

代码:

#define MAX_N 1005
int data[MAX_N];
int n,k;
// 从前i项得到的和sum
bool DFS(int i,int sum)
{
	// n项都计算过了,判断是否等于k
	if(i == n)
		return sum == k;
	// 不加上第i项
	if(DFS(i+1,sum))
		return true;
	// 加上第i项
	if(DFS(i+1,sum+data[i]))
		return true;
	
	return false;
}

结果:


        嗯,一个简单的小例子,就算是比赛一般也就大一前3题吧。

例题2:

        有一个大小为* M的院子,雨后积起了水。‘W’代表积水,'.'代表没有积水。八连通的积水被认为是连接在一起的。请求出院子里总共有多少水洼?(限制条件:N,M<=100)

(八连通表示:上,下,左,右,左上,左下,右上,右下都属于直接连通。下图相对于W的*部分

* * *

*W*

* * *


代码:

#define MAX_N 100

int N,M;
int Map[100][100];

void DFS(int x,int y)
{
	Map[x][y] = '.';	// 判断过的位置变为'.'没有积水
	// 判断连通的八个位置
	for(int dx=-1;dx<=1;dx++)
		for(int dy=-1;dy<=1;dy++)
		{
			int Nx = x + dx;
			int Ny = y + dy;
			if(Map[Nx][Ny] == 'W' && Nx>=0 && Nx<N && Ny>=0 && Ny<M)
				DFS(Nx,Ny);
		}
	return ;
}
int Solve()
{
	int Ans = 0;
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
		{
			if(Map[i][j] == 'W')
			{
				// 每一次走入该判断中,代表新增一个水洼,同时把该水洼所有的'W'全改为'.'
				Ans++;
				DFS(i,j);
			}
		}
	return Ans;
}
结果:


测试的数据:

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
一会儿会更新BFS,最近看动态规划有点迷惑,可能会晚一些。



  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值