第十一天:深度优先搜索(DFS)

今天是释然发题解的第十一天,以后每一天都会和大家分享学习路上的心得,希望和大家一起进步,一起享受coding的乐趣。
本文约1600字,预计阅读5分钟
昨天我们学习了二分,忘记的小伙伴们可以看一下哦:

二分查找

哎,释然啊,释然去期中考试辽。。。太难了,将近一个月没有更新,还是因为太懒了,不能再这样了,害,希望大家好好监督我,嗯…
今天我们来聊一聊的深度优先搜索的相关问题,明天和大家分享分治的相关知识:

定义:来源挑战程序设计竞赛

深度优先搜索( DFS,Depth-First Search) 是搜索的手段之一。 它从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直至找到最终的解。
例如求解数独,首先在某个格子内填入适当的数字,然后再继续在下一个格子内填入数字,如此继续下去。如果发现某个格子无解了,就放弃前一一个格 子上选择的数字,改用其他可行的数字。
根据深度优先搜索的特点,采用递归函数实现比较简单。

深入了解

其实深度优先搜索如果用树或者图的搜索去理解会非常好理解,二叉树的遍历其实用的就是搜索的思想,从一个根节点遍历所有的子节点,搜索+回溯,直到遍历所有节点。深度优先搜索其实利用了栈来调用,深搜的空间大小是与搜索的深度成正比。

举一个栗子:

第一个例题:湖泊计数

来源:北京大学OJ:NO.2386
描述:
由于最近的降雨,在农夫约翰田地的不同地方积聚了水,用N x M(1 <= N <= 100; 1 <= M <= 100)正方形的矩形表示。每个方格包含水(‘W’)或旱地(’。’)。农夫约翰想弄清楚他的田地里形成了多少个池塘。池塘是一组相连的正方形,里面有水,其中一个正方形被认为与八个池塘相邻。

给定农夫约翰的田野图,确定他有多少个池塘。
输入项:
*第1行:两个以空格分隔的整数:N和M

*第2…N + 1行:每行M个字符,代表Farmer John字段的一行。每个字符都是“ W”或“ . ”,字符之间没有空格。
输出量:
*第1行:农夫约翰田间的池塘数。
样本输入

8 12
. WWW . . . . . WWW
. . . . W W . . . WW .
. . . . WW . . . W . .
. . . . . W . . . W . .
. . . . . W . . . W . .
.WW . . . .WW. . .
WWW . . . . WW . . .
. . W . . . . . . .WW .
样本输出

3
提示

输出详细信息:

有三个池塘:一个在左上角,一个在左下角,另一个在右侧

解题思路一:深度优先搜索

每个W所相连的八个方向都可能存在水,因此沿八个方向搜索,找到W就把它替换成“ . ”,然后继续搜索,直到所有的都变成“ . ”,八个方向共八个状态转移,所以时间复杂度为O(8MN)

void dfs(int x, int y)
{
	map[x][y] = '.';
	for (int dx = -1; dx <= 1; dx++)
	{
		for (int dy = -1; dy <= 1; dy++)
		{
			x += dx, y += dy;
			if (x >= 1 && x <= M && y >= 1 && y <= N && map[x][y]=='W')
				dfs(x,y);
		}
	}
	return ;
}

这就是整个程序的主体部分,主函数就是输入和一个一个搜索每一个格子,然后每次搜索完毕以后,增加一次

int main()
{
	int i,j,sum;
	for (i = 1; i <= M; i++)
	{
		for (j = 1; j <= N; j++)
		{
			cin>>map[i][j];
		}
	}
	for (i = 1; i <= M; i++)
	{
		for (j = 1; j <= N; j++)
		{
			if( map[i][j]=='W')
			{dfs(i,j);
			sum++;}
		}
	}
	cout<<sum<<endl;
	return 0;
}

好了,今天的有关深度优先搜索的题目就到这里
释然每天发布一点自己学习的知识,希望2年后我们也能在ACM的赛场上见面,一起去追寻自己的程序猿之路吧!

后期也会和大家一起分享学习心得和学习经验呢,明天我们不见不散哦!

下期预告:

广度优先搜索

如果大家有什么建议或者要求请后台留言,释然也想和大家一起进步呀!
联系方式:shirandexiaowo@foxmail.com

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shirandexiaowo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值