池塘抽水 c++ dfs

这篇博客介绍了一个关于池塘抽水的C++深度优先搜索算法问题。题目要求计算在给定的M*N地块中,至少需要多少台抽水机才能抽干所有相连的池塘。解题思路是遍历地图,遇到池塘使用DFS进行搜索并标记已抽干,最终输出抽水机数量。博客提供了详细的解题思路、样例图解和完整代码。

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

题目描述

池塘抽水

  你刚刚承包了一块大小为 M * N (1<=M, N<=1000)的地块,现要利用这片区域开发成商业用地,但之前该地块是一个渔场所在地,因此分布着许多大小不一的池塘,现在需要把所有的这些池塘里的水抽干并填平。 现在你想知道至少需要多少台抽水机器才能将这片区域的所有池塘抽干。如果池塘的区域互相连接,那么这些区域可以使用同一台机器。例如:若 M = 1, N = 5,其中(1, 1), (1, 2)和(1, 4)区域有池塘,那么由于(1, 1)和(1, 2)这两块区域连在一起,所以只需要两台机器即可采完所有池塘。(注意,池塘如果上、下、左、右相邻以及对角线相邻都属于相连的情况)

输入格式

  输入的数据有多组,每组数据首先是两个正整数 M 和 N,表示地块的尺寸,接下来是一个 M 行N 列的矩阵,矩阵中有两种可能的值,一种是“*”,表示此处没有池塘,一种是“@”,代表此处为池塘。若 M, N 均为 0,则表示输入结束,该组数据无需输出任何结果。

输出格式

​  对于每组数据,在一行内输出需要的抽水机器数量。

输入样例

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

输出样例

0
1
2
2

解题思路

题意

  简单的说,题目是求独立的池塘的个数。把地块按下标分成 M * N 的方格,每个池塘方格与上、下、左、右相邻以及对角线相邻的池塘方格相连。输入中 * 表示没有池塘的方格, @ 表示有池塘的方格。当输入(0,0)时,结束输出。

思路

  遍历所有的地块方格,每找到一个池塘方格,放置抽水机将这一整片池塘抽干(把 @ 变成 * 或者其他字符),重复操作直到遍历结束,得到总共抽干池塘的次数也就是需要的抽水机数量。

  使用深度优先搜索思想,先定位到一个池塘方格,把当前方格抽干并依次往相邻的八个方向移动,继续抽干当前的池塘方格和向周围搜索的操作,直到移动到地图边界或者非池塘的方格,不做任何操作并返回上一个方格,继续向其它方向搜索。最终回到初始位置完成递归搜索。因为递归过程是将当前的池塘方格抽干并移动至周围的方格,当前方格的状态不影响移动操作,所以不需要额外的回溯操作。

样例图解

5    5
*  *  *  *  @
*  @  @  *  @
*  @  *  *  @
@  @  @  *  @
@  @  *  *  @

用蓝色方格代表池塘方格,绿色方格代表非池塘方格。

地块原状态
请添加图片描述

从(1,1)位置从左往右、从上往下遍历,找到第一个位置(1,5),放入第一台抽水机
在这里插入图片描述

进行递归抽水的操作,首先将当前位置池塘方格抽干
在这里插入图片描述
然后判断,左下、左、左上、上、右上、右、右下均不合要求,移动到下面一格
请添加图片描述
重复抽水和移动操作至填满当前池塘
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

请添加图片描述
无可抽水位置,按移动位置依次回退,每回退一个位置继续判断是否可以抽水
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回到初始位置(1,5),判断结束后退出抽水操作并开始搜索下一个池塘方格位置,放置第二台抽水机(2,2)
在这里插入图片描述
继续抽水并以左下,左,左上,上,右上,右,右下,下的顺序移动搜索
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
依次回退上一位置并继续判断,直到回到第二台抽水机位置(2,2),完成抽水操作。
在这里插入图片描述
继续搜索放置饮水机的位置,遍历完地块后算法结束
在这里插入图片描述
总共抽水机台数为2台

解题代码

定义变量

定义地块方格数组 block 和地块尺寸变量 M、N,记录抽水机数量的变量 cnt

const int SIZE = 1007;
int cnt = 0;
int M, N;
char block[SIZE][SIZE];

定义实现左下、左、左上、上、右上、右、右下、下移动的数组

int x[8] = {
    1, 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值