## [$AcWing$ $1097$. 池塘计数](https://www.acwing.com/problem/content/1099/) ### 一、题目描述 农夫约翰有一片 $N∗M$ 的矩形土地。 最近,由于降雨的原因,部分土地被水淹没了。 现在用一个字符矩阵来表示他的土地。 每个单元格内,如果包含雨水,则用 $W$ 表示,如果不含雨水,则用 $.$表示。 现在,约翰想知道他的土地中形成了多少片池塘。 **每组相连的积水单元格集合可以看作是一片池塘**。 每个单元格视为与其 **上、下、左、右、左上、右上、左下、右下** 八个邻近单元格相连。 请你输出共有多少片池塘,即矩阵中共有多少片相连的 $W$块。 **输入格式** 第一行包含两个整数 $N$ 和 $M$。 接下来 $N$ 行,每行包含 $M$ 个字符,字符为”$W$”或”$.$”,用以表示矩形土地的积水状况,字符之间没有空格。 **输出格式** 输出一个整数,表示池塘数目。 **数据范围** ```cpp {.line-numbers} 1≤N,M≤1000 ``` **输入样例**: ```cpp {.line-numbers} 10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W. ``` **输出样例**: ```cpp {.line-numbers} 3 ``` ### 二、总结 $Flood \ Fill$问题比较经典的作法有两种: **宽搜** 和 **深搜**,代码写好的话,两种方法没有区别,不存在说数据量大了就深搜不了的问题。 要严格使用$yxc$老师讲的$hh=0,tt=-1$的模拟队列方式,不要使用$STL$中的$queue$!,原因很简单,有时候,比如斜率优化中,我们可能还要从队头出队列,那样的话还需要使用 **双端队列** ,还如直接来这个模拟更方便! ### 三、广度优先搜索 ```cpp {.line-numbers} #include using namespace std; const int N = 1010, M = N * N; typedef pair PII; #define x first #define y second // 方向数组 int dx[] = {1, 0, -1, 0, 1, -1, 1, -1}; int dy[] = {0, 1, 0, -1, 1, -1, -1, 1}; int n, m; char g[N][N]; int ans; PII q[M]; // 宽搜 void bfs(int sx, int sy) { int hh = 0, tt = -1; q[++tt] = {sx, sy}; // 起点入队列 g[sx][sy] = '.'; // 标识为已使用过,防止回头路 while (hh <= tt) { PII t = q[hh++]; // 一边取队列头,一边出队列 for (int i = 0; i < 8; i++) { int tx = t.x + dx[i]; int ty = t.y + dy[i]; if (g[tx][ty] == 'W') { g[tx][ty] = '.'; q[++tt] = {tx, ty}; } } } } int main() { // n行m列  cin >> n >> m; // 读入地图 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> g[i][j]; // 枚举每个位置 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (g[i][j] == 'W') { bfs(i, j); // 开始宽搜 ans++; // 找到一块 } printf("%d\n", ans); return 0; } ``` ### 四、深度优先搜索 ```cpp {.line-numbers} #include using namespace std; const int N = 1010; int n, m, ans; char g[N][N]; // 方向数组 int dx[] = {1, 0, -1, 0, 1, -1, 1, -1}; int dy[] = {0, 1, 0, -1, 1, -1, -1, 1}; void dfs(int x, int y) { g[x][y] = '.'; // 这样可以不用使用st数组,妙! for (int i = 0; i < 8; i++) { int tx = x + dx[i], ty = y + dy[i]; if (g[tx][ty] == 'W') dfs(tx, ty); } } int main() { cin >> n >> m; // 使有深度优先搜索时,注意下标从1开始,这样相当于构建了一个四周为0的墙,不会越界 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) cin >> g[i][j]; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (g[i][j] == 'W') { // 找到“ W ”. dfs(i, j); ans++; // 统计答案 } printf("%d\n", ans); return 0; } ```