P1596 [USACO10OCT] Lake Counting S——DFS、连通性问题

题目描述

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. Given a diagram of Farmer John's field, determine how many ponds he has.

输入格式

Line 1: Two space-separated integers: N and M * Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

输出格式

Line 1: The number of ponds in Farmer John's field.

输入输出样例 #1

输入 #1

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

输出 #1

3

说明/提示

OUTPUT DETAILS: There are three ponds: one in the upper left, one in the lower left, and one along the right side.

题解

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

const int MAXN = 105;
vector<string> field;
bool visited[MAXN][MAXN];
int n, m;

// 八个方向的偏移量
int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};

// 深度优先搜索函数,用于标记一个池塘的所有水
void dfs(int x, int y) {
    visited[x][y] = true;
    // 遍历八个方向
    for (int i = 0; i < 8; ++i) {
        int nx = x + dx[i];
        int ny = y + dy[i];
        // 检查新位置是否合法且为水且未被访问
        if (nx >= 0 && nx < n && ny >= 0 && ny < m && field[nx][ny] == 'W' && !visited[nx][ny]) {
            dfs(nx, ny);
        }
    }
}

int main() {
    cin >> n >> m;
    field.resize(n);
    for (int i = 0; i < n; ++i) {
        cin >> field[i];
    }

    int pondCount = 0;
    // 初始化访问标记数组
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            visited[i][j] = false;
        }
    }

    // 遍历整个农田
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (field[i][j] == 'W' && !visited[i][j]) {
                dfs(i, j);
                pondCount++;
            }
        }
    }

    cout << pondCount << endl;
    return 0;
}

dfs(深度优先搜索)函数在这个问题中的主要作用之一就是标记与当前位置相连的所有水区域,避免重复计算,从而准确统计出池塘的数量。下面详细解释其具体作用:
当我们在遍历农田时,一旦发现一个未被访问过的水位置(字符为 'W'),就意味着可能找到了一个新的池塘的起始点。此时调用 dfs 函数,从这个起始点开始向其八个相邻方向进行深度优先搜索。
在搜索过程中,每到达一个合法的水位置(即该位置在农田范围内、是水且未被访问过),就将其标记为已访问(visited[x][y] = true)。通过递归地对相邻位置进行搜索,dfs 函数会不断深入探索,将与起始点相连的所有水位置都标记为已访问。
由于每个池塘是一个连通的水区域,在搜索过程中如果不进行标记,可能会多次访问同一个水位置,导致对同一个池塘进行重复计数。通过使用 visited 数组标记已访问的位置,当再次遇到这些位置时,就不会再次将其作为新池塘的起始点进行搜索,从而保证每个池塘只被统计一次。

posted @ 2025-02-22 12:11  ToFuture$  阅读(28)  评论(0)    收藏  举报