题目描述:给定一个N×M的字符矩阵,其中的元素由'W'和'.'组成,其中'W'代表有积水,'.'代表没有积水,八连通的积水可看成连在一起形成一个水洼,所谓八连通就是以当前位置为中心的八个方向,若相邻任一方向上有积水,则可以互连形成同一个水洼,问该矩阵土地上有多少个水洼?
输入描述:第一行输入正整数N和M,再输入N×M的字符矩阵
输出描述:水洼的个数
输入示例
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
示例说明:三个水洼分别在矩阵土地的左上部分、右部分,左下部分
解题思路:(参考自《挑战程序设计竞赛》一书):这是一道经典的深度优先搜索(DFS)题,从任意的W开始,不停地把邻接的部分(八连通)用 '.' 代替。1次DFS后与初始的这个W连接的所有W就都被替换成了'.',因此直到图中不在存在W为止,总共进行DFS的次数就是答案了。8个方向的共对应了8种状态转移,每个格子作为DFS的参数至多被调用一次。
时间复杂度:O(8×M×N)=O(M×N)
coding:

#include<iostream>
#include<algorithm>       //注意POJ不支持<bits/stdc++.h>,老老实实写头文件
using namespace std;

int N,M;                  //注意要定义成全局变量
char a[100][100];         //最大的field矩阵

void dfs(int i,int j)
{
    a[i][j]='.';        //当前位置是'W',将其替换成'.' ,很容易忽视的一步
    int nx,ny;          //如果当前位置的邻近(八连通)有积水,则记录其坐标为(nx,ny)
    for(int dx=-1;dx<=1;dx++)
        for(int dy=-1;dy<=1;dy++)
        {   //要搜索完八个方向,简化成两个方向,即横向和纵向
            nx=i+dx; ny=j+dy;
            if(nx>=0 && nx<=N && ny>=0 && ny<=M && a[nx][ny]=='W')
            {    //要确保搜索位置没有超出矩阵范围并且该位置有积水,才开辟新的搜索
                dfs(nx,ny);
            }
        }
}

int main()
{

    cin>>N>>M;               //输入第一行
    for(int i=0;i<N;i++)     
        for(int j=0;j<M;j++)
        {
            cin>>a[i][j];     //field矩阵的建立
        }
    int ans=0;                //ponds个数,也就是DFS次数

    for(int i=0;i<N;i++)
        for(int j=0;j<M;j++)
        {
            if(a[i][j]=='W')
            {
                dfs(i,j);
                ans++;
            }
        }
    cout<<ans<<endl;
}