Lake Counting——八连通的积水(深度优先搜索)

题目

有一个大小为 N × M N\times M N×M的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少水洼?八连通指的是下图中相对 W W W ∗ * 的部分,'W'表示积水,''表示没有积水;

∗ ∗ ∗ ***
∗ W ∗ *W* W
∗ ∗ ∗ ***

输入

N = 10 , M = 12 N=10,M=12 N=10,M=12
W********WW*
*WWW*****WWW
****WW***WW*
*********WW*
*********W**
**W******W**
*W*W*****WW*
W*W*W*****W*
*W*W******W*
**W*******W*

输出

3

分析

采用深度优先搜索的思路,从任意的W位置开始,不停的把邻接的W替换成*,1次dfs()之后与初始的这个W相连的所有W就都被替换成了*,循环遍历数组,直至没有W,那么总共进行的dfs()的次数就是连通的积水数。

8个方向共对应了8种状态转移,每个格子作为dfs()的参数至多被调用一次(即若当前格子满足dfs()条件,则dfs()中又会有8次循环),所以时间复杂度为 O ( 8 × N × M ) = O ( N × M ) O(8\times N\times M)=O(N\times M) O(8×N×M)=O(N×M)

代码

#include 
#include 
using namespace std;
#define MAX_SIZE 100

char field[MAX_SIZE][MAX_SIZE+1];

void dfs(int x, int y, int n, int m){
    field[x][y] = '*';	//把当前位置替换成'*'
    for(int dx=-1; dx<=1; dx++){	//循环遍历8个方向
        for(int dy=-1; dy<=1; dy++){
            int nx = x + dx, ny = y + dy;	//下一个位置
            if(0 <= nx && nx < n && 0 <= ny && ny < m && field[nx][ny] == 'W')
                dfs(nx, ny, n, m);	//若满足条件,再次进行dfs
        }
    }
}

int main(){
    int n, m, res = 0;
    scanf("%d %d", &n, &m);
    for(int i=0; i<n; i++)
        scanf("%s", field[i]);
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(field[i][j] == 'W'){
                dfs(i, j, n, m);	//满足条件,进行dfs
                res++;
            }
        }
    }
    printf("%d\n", res);
    return 0;
}

输出

Lake Counting——八连通的积水(深度优先搜索)_第1张图片

你可能感兴趣的:(挑战程序设计竞赛)