题目:
某石油公司勘探地下油田资源,在一长方形区域中工作。他们的勘探方案是,首先将油田划分成许多小正方形区域,然后分别探测每一块小正方形区域是否有油。含有油就为油田。如果相邻两个(水平、垂直或对角线相邻)油田,就位相同油藏的一部分。油藏尽可能多的包含油田(油田的个数不超过100)。你的工作是确定这个长方形地域中包含多少个不同的油藏。
输入:
输入文件中包含一个或多个长方形地域。每个地域的第一行都有两个正整数m和n(1<=m,n<=100),表示地域的行数和列数。如果m=0,则表示输入结束;否则此后有m行,每行都有n个字符。每个字符都对应一个正方形区域,字符*表示没有油田,字符@表示有油。
输出:对于每个长方形区域,都单行输出油藏的个数。
输入样例:
1 1
*
3 5
@@*
@
@@*
1 8
@@***@
5 5
****@
@@@
@**@
@@@@
@@**@
0 0
输出样例
0
1
2
2
题解:
对于这样的油田遍历,从每个“@”格子出发,寻找特它周围所有的“@”格子,同时将这些格子标记一个连通分量号,最后数连通分量数。使用图的深度优先搜索即可。
样例4,其油藏的个数就是连通分量的个数,如下图
八个方向的坐标变化,注意写代码是判断越界
代码:
#include<bits/stdc++.h>
#define REP(i,b,e) for(int i=(b);i<=(e);i++)
using namespace std;
const int maxn=100+5;
string str[maxn];//存储字符矩阵
int m,n,setid[maxn][maxn];//行列,连通分量号
void dfs(int x,int y,int id)//行列和连通分量号
{
if(x<0||x>=m||y<0||y>=n) return ;//出界
if(setid[x][y]>0||str[x][y]!='@') return ;//已有连通分量号或不是'@'
setid[x][y]=id;
REP(dx,-1,1)
REP(dy,-1,1)
if(dx!=0||dy!=0)
dfs(x+dx,y+dy,id);//八个方向深搜 ,把连通的都赋值一样的数值,就是连通分量号,总之不为0
}
int main()
{
while((cin>>m>>n)&&m&&n)
{
REP(i,0,m-1)
cin>>str[i];
memset(setid,0,sizeof(setid));
int cnt=0;
REP(i,0,m-1)
REP(j,0,n-1)
if(setid[i][j]==0&&str[i][j]=='@')//只要为0就表示没有搜过,或者和别的块不连通,就可以是一个新的油藏
dfs(i,j,++cnt);
cout<<cnt<<endl;
}
return 0;
}