AcWing 1097 池塘計數

題目描述:

農夫約翰有一片 N∗M 的矩形土地。

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

現在用一個字符矩陣來表示他的土地。

每個單元格內,如果包含雨水,則用”W”表示,如果不含雨水,則用”.”表示。

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

每組相連的積水單元格集合可以看作是一片池塘。

每個單元格視爲與其上、下、左、右、左上、右上、左下、右下八個鄰近單元格相連。

請你輸出共有多少片池塘,即矩陣中共有多少片相連的”W”塊。

輸入格式

第一行包含兩個整數 N 和 M。

接下來 N 行,每行包含 M 個字符,字符爲”W”或”.”,用以表示矩形土地的積水狀況,字符之間沒有空格。

輸出格式

輸出一個整數,表示池塘數目。

數據範圍

1≤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

分析:

終於基本刷完了DP章節的題目,可以進入和藹可親的搜索章節了。本題是Flood Fill的典型例題,顧名思義,洪水覆蓋,地面上有高地和窪地,洪水會逐漸擴散直至覆蓋所有的窪地。Flood Fill問題可以用DFS或者BFS解決,一般還是採用BFS,可以防止爆棧,畢竟函數內部的棧空間只有1M大小。

本題比較簡單,就簡單的說下基本的解題思路吧。首先,題意是求八連通塊的數目,八連通塊的遍歷和四連通塊一樣,都可以使用方向向量dx和dy,遍歷特定的座標而不用使用二重循環遍歷矩形的區域。之前實現BFS習慣直接使用queue,現在習慣了直接用數組模擬隊列的便捷和快速,就直接用數組模擬的隊列實現了。基本思路是,將當前座標入隊,同時置訪問位爲true,當隊列非空時,取出隊頭元素,嘗試遍歷隊頭元素周圍的八連通區域,當到達每個位置的座標合法時,就將該位置的座標也入隊。判斷某個位置是否合法,只需要判斷該位置是否已經訪問過,是否超過了單元格的邊界,以及是否不含雨水不能通行。

這裏是在每個元素入隊時就將訪問位置爲true,實際上記錄的是discovered時間,如果遍歷完該元素周圍所有的元素再置爲true,記錄遍歷元素的visited時間也是可以的,簡易版的BFS程序不論是入隊時置爲已訪問,還是出隊時或者遍歷完時都無關緊要。

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1005;
typedef pair<int,int> PII;
char g[N][N];
bool st[N][N];
PII q[N * N];
int n,m;
int dx[] = {0,0,-1,1,-1,-1,1,1};
int dy[] = {1,-1,0,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 nx = t.first + dx[i],ny = t.second + dy[i];
            if(st[nx][ny]||g[nx][ny]=='.'||nx<0||nx>=n||ny<0||ny>=m)    continue;
            q[++tt] = {nx,ny},st[nx][ny] = true;
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 0;i < n;i++)   scanf("%s",&g[i]);
    int res = 0;
    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);
                res++;
            }
        }
    }
    printf("%d\n",res);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章