题目描述:给定一个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;
}
京公网安备 11010502036488号