《Lake Counting》院子积水问题

Lack Counting

题目来自挑战《挑战程序设计竞赛》穷竭搜索(POJ No.2386)

题目

有一个大小为 N×M 的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出
园子里总共有多少水洼?(八连通指的是下图中相对 W 的.的部分)
其中W是积水,.是干地

. . .
. W .
. . .

限制条件

N,M<=100

样例

输入

N=10, M=12
园子如下图('W’表示积水, '.'表示没有积水)
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

输出

3

题意

这个题就是让你求院子里有几个水洼,怎么才能算一个水塘呢,连在一起的水洼构成一个水塘,怎么算连在一起呢,如果自身是积水,它的上下左右、左上、左下、右上、右下,八个方向的积水都与自身相连。就是求最大连通图的个数。上述题目肉眼可见是三个水洼。

解题思路

从任意的W开始,不停的把邻接的部分用**’.‘代替。1次DFS后,与这个W邻接的所有W都变成了’.’**,因此到图中不在存在W为止。总共进行DFS的次数就是水洼个数。

代码

#include <iostream>
#include <vector>
using namespace std;

//深度优先搜索,从x,y这一点向周围八个点搜索
void DFS(vector<vector<char> >& g,int n,int m,int x,int y)
{
	//每次向周围搜索前,先将x,y这点置为'.',可以理解为遍历过就当作是干地,下次不再遍历
	g[x][y] = '.';
	//向周围八个点开始搜索
	for (int  i = -1; i <= 1; i++) //i = -1的意思是,从(x,y)点的最左边开始搜索
	{
		for (int j = -1; j <= 1; j++) //j = -1 的意思是,从(x,y)点的最上边开始搜索
		{
			//先判断是否超过范围,再判断是否是水池‘W’,如果是,则以这一点继续深搜
			if (x + i >= 0 && x + i < n && y + j >= 0 && y + j < m && g[x + i][y + j] == 'W')
				DFS(g, n, m, x + i, y + j);
		}
	}

}

//求水洼数量
int LakeCounting(vector<vector<char> >& g,int n,int m)
{
	int res = 0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (g[i][j] == 'W')
			{
				DFS(g,n,m,i,j); //这里的DFS调用相当于搜索极大连通图,DFS里面的是小连通图
				++res;          //极大连通图的数量就是水洼的数量
			}
		}
	}
	return res;
}

int main()
{
	int n = 0, m = 0;
	cin >> n >> m;
	vector<vector<char> > g(n);
	//输入
	for (int i = 0; i < n; i++)
	{
		g[i].resize(m);
		for (int j = 0; j < m; j++)
			cin >> g[i][j];
	}
	//输出
	cout << LakeCounting(g,n,m) << endl;
			

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值