acwing \1097. 池塘计数

题目传送门

dfs题目描述

农夫约翰有一片 N∗MN∗M 的矩形土地。

最近,由于降雨的原因,部分土地被水淹没了。

现在用一个字符矩阵来表示他的土地。

每个单元格内,如果包含雨水,则用”W”表示,如果不含雨水,则用”.”表示。

现在,约翰想知道他的土地中形成了多少片池塘。

每组相连的积水单元格集合可以看作是一片池塘。

每个单元格视为与其上、下、左、右、左上、右上、左下、右下八个邻近单元格相连。

请你输出共有多少片池塘,即矩阵中共有多少片相连的”W”块。

输入格式

第一行包含两个整数 NN 和 MM。

接下来 NN 行,每行包含 MM 个字符,字符为”W”或”.”,用以表示矩形土地的积水状况,字符之间没有空格。

输出格式

输出一个整数,表示池塘数目。

数据范围

1≤N,M≤10001≤N,M≤1000

输入样例:

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

输出样例:

3

算法求解

分析

st[i][j]表示一个点有没有被dfs放过过

遍历整个图

  • 遇到没有被访问过,并且是W的点,计数+1;从该点进行dfs,对其连通的所有W标记访问过

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1010;
char g[N][N]; // 
int n, m;
int res; 
bool st[N][N]; // 标记是不是被访问过了 
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[8] = {0, -1, -1, -1, 0, 1, 1, 1};

void dfs(int x, int y)
{
	st[x][y] = true;
	
	for(int i = 0; i < 8; i++)
	{
		int nx = x + dx[i], ny = y + dy[i];
		if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && g[nx][ny] == 'W' && !st[nx][ny])
		{
			dfs(nx, ny);		
		}
	 } 
} 

int main()
{
	scanf("%d%d", &n, &m);
	getchar();
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			scanf("%c", &g[i][j]);	
		}	
		getchar();	
	}	
	
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			if(!st[i][j] && g[i][j] == 'W')
			{
				dfs(i, j);
				res ++;
			}
		}
	}
	cout << res << endl;
	return 0;
} 

时间复杂度

\(O(m*n)\)

参考文章

posted @ 2022-03-05 15:28  VanHope  阅读(88)  评论(0)    收藏  举报