池塘计数 题型:Flood Fill 算法 连通块的个数

80 阅读2分钟

P1596 [USACO10OCT] Lake Counting S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

就是有一个二维空间

里面有水的用‘W’表示,无水的用‘.’表示

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

问共有几个池塘。

输入样例

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

样例解析

一共有三个池塘: image.png

其实就是让我们找连通块的。

解题思路

按层遍历,如果是水我们就把水四周是水的地方全部遍历一遍,那么第一次第一个水池就被我们遍历完了,所有遍历过的地方都打上标记,防止二次遍历:

image.png

然后我们再接着第一行找没有被遍历过的水池:

image.png

找到之后我们就把它四周的没有被遍历过的水池全部遍历完: image.png

然后回到第二行接着往下遍历,直到遍历到一个没有被遍历过的水池:

image.png

就把它周围全部遍历一遍:

image.png

code

两个 bfs()函数都可以 bfs写法

#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
const int N = 1010, M = N * N;;
typedef pair<int, int>PII;
int n, m,cnt;
char g[N][N];
bool st[N][N];
PII q[M];
int dx[8] = { 0,1,0,-1,1,1,-1,-1 };
int dy[8] = { 1,0,-1,0,1,-1,1,-1 };
void bfs(int x, int y)
{
	int hh = 0, tt = 0;
	q[0] = { x,y };
	st[x][y] = true;

	while (hh <= tt)
	{
		PII t = q[hh++];

		for (int i = 0; i < 8; i++)
		{
			int tx = t.x + dx[i], ty = t.y + dy[i];
			if (tx < 0 || tx >= n || ty < 0 || ty >= m || st[tx][ty]||g[tx][ty]=='.')continue;
			q[++tt] = { tx,ty };
			st[tx][ty] = true;
		}
	}
}

//void bfs(int x, int y) {
//    q.push({ x, y });
//    st[x][y] = true;
//
//    while (!q.empty()) {
//        PII t = q.front();
//        q.pop();
//
//        for (int i = t.x - 1; i <= t.x + 1; i++) {
//            for (int j = t.y - 1; j <= t.y + 1; j++) {
//                if (i == t.x && j == t.y) continue;  // Skip the current cell
//                if (i < 0 || i >= n || j < 0 || j >= m || st[i][j] || g[i][j] == '.') continue;
//                q.push({ i, j });
//                st[i][j] = true;
//            }
//        }
//    }
//}
//void bfs(int x, int y) {
//    q.push({ x, y });
//    st[x][y] = true;
//
//    while (!q.empty()) {
//        PII t = q.front();
//        q.pop();
//
//        for (int i = t.x - 1; i <= t.x + 1; i++) {
//            for (int j = t.y - 1; j <= t.y + 1; j++) {
//                if (i == t.x && j == t.y) continue;  // Skip the current cell
//                if (i < 0 || i >= n || j < 0 || j >= m || st[i][j] || g[i][j] == '.') continue;
//                q.push({ i, j });
//                st[i][j] = true;
//            }
//        }
//    }
//}
int main()
{
	cin >> n >> m;

	for (int i = 0; i < n; i++)cin >> g[i];

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (g[i][j] == 'W' && !st[i][j])
			{
				bfs(i, j);
				cnt++;
			}
		}
	}

	cout << cnt << endl;

	return 0;
}

image.png

dfs写法

#include<bits/stdc++.h>
using namespace std;
const int N = 1010, M = N * N;;
int n, m,cnt;
char g[N][N];
bool st[N][N];
int dx[8] = { 0,1,0,-1,1,1,-1,-1 };
int dy[8] = { 1,0,-1,0,1,-1,1,-1 };
void dfs(int x, int y)
{
	    st[x][y] = true;
		for (int i = 0; i < 8; i++)
		{
			int tx =x + dx[i], ty = y + dy[i];
			if (tx < 0 || tx >= n || ty < 0 || ty >= m || st[tx][ty]||g[tx][ty]=='.')continue;
			dfs(tx,ty);
		}
	
}
int main()
{
	cin >> n >> m;

	for (int i = 0; i < n; i++)cin >> g[i];

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (g[i][j] == 'W' && !st[i][j])
			{
				dfs(i, j);
				cnt++;
			}
		}
	}

	cout << cnt << endl;

	return 0;
}

image.png