油田(Oil Deposits, UVa 572)
题意:
多组案例,每组案例输入一个m行n列的字符矩阵,统计字符‘@’组成多少个连通块。如果两个字符‘@’所在的格子相邻(横、竖或对角线),则说明它们属于同一连通块。
案例:
Sample Input
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
Sample Output
0
1
2
2
用DFS求连通块,从每个‘@’格子出发,递归其周围的‘@’格子,每访问一个格子时给其写上连通编号,避免同一格子访问多次。
//优先搜索@的周围8个
#include<iostream>
#include<cstring>
const int maxn=105;
char pic[maxn][maxn];
int m,n;
int idx[maxn][maxn]; //标记,避免多次访问
void dfs(int r,int c,int id)
{
if(r<0||r>=m||c<0||c>=n) //出界了
return;
if(idx[r][c]>0||pic[r][c]!='@') return;
idx[r][c]=id; //连通分量编号
for(int dr=-1;dr<=1;dr++) //周围那8块
{
for(int dc=-1;dc<=1;dc++)
{
if(dr!=0||dc!=0)
dfs(r+dr,c+dc,id);
}
}
}
int main()
{
while(cin>>m>>n&&m&&n)
{
for(int i=0;i<m;i++)
{
cin>>pic[i];
}
memset(idx,0,sizeof(idx));
int cnt=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(idx[i][j]==0&&pic[i][j]=='@')
dfs(i,j,++cnt); //进入判断第一个连通块
}
}
cout<<cnt<<endl;
}
return 0;
}