Oil Deposit(九度 OJ 1460)
1.题目描述:
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It
then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil
deposits are contained in a grid.
输入:
The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100.Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either ‘’, representing the absence of oil, or “@”, representing an oil pocket.
输出:
For each grid, output the number of distinct oil deposits. Two different pockets
are part of the same oil deposit if they are adjacent horizontally, vertically, or
diagonally. An oil deposit will not contain more than 100 pockets.
样例输入:
1 1
*
3 5
@@
@
@@*
1 8
@@***@
5 5
****@
@@@
@**@
@@@@
@@**@
0 0
样例输出:
0
1
2
2
2.基本思路
该题看上去也是搜索问题,但其不属于排列树问题也不属于子集树问题。这里最简单粗暴的方法就是直接把所有的结点遍历一遍,然后每遍历一个结点时,判断其是否是新引入的油田,如果是的话,答案+1,并采用dfs并将其所有邻居的油田都标记为已访问。然后最后统计得到连通分量的个数输出答案。
这里我们采用DFS的方法来辅助搜索,代码的书写会更加的简洁。在遍历每一个结点的时,如果它是合法@结点且未被访问过,答案+1,同时利用DFS的方法对其直接或间接相邻的油田进行已访问标记,通过DFS我们可以将该结点连通分量里面的所有@结点都标记为已访问的状态。其类似于图像处理中的洪水填充法(Foold Fill)。有了DFS辅助我们的遍历搜索过程便可以通过精简的代码完成整个过程啦。
3.代码实现
#include <iostream>
#define M 101
#define N 101
using namespace std;
int map[M][N];
bool mark[M][N];
int dir[8][2]={{-1,0},{1,0},{0,1},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}};
int ans;
int m,n;
void dfs(int x,int y){
for(int i=0;i<8;i++){
int newx = x+dir[i][0];
int newy = y+dir[i][1];
if(mark[newx][newy])continue;//判断是否已经访问过
if(newx<0||newx>=m||newy<0||newy>=n)continue;//是否越界
if(!map[newx][newy]==1)continue;//只对油田进行扩展
mark[newx][newy]=true;
dfs(newx,newy);
}
}
int main()
{
char c;
while(~scanf("%d%d",&m,&n)){
ans=0;//初始化
if(m==0&&n==0)break;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
mark[i][j]=false;//初始化
cin>>c;
if(c=='*'){
map[i][j]=0;
}
else{
map[i][j]=1;
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(map[i][j]==1&&mark[i][j]==false){
ans++;
dfs(i,j);//Flood Fill
}
}
}
printf("%d\n",ans);
}
return 0;
}
/*
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
*/
在编码的过程中有个需要注意的细节就是字符的输入,我们不能用scanf("%c",&map[i][j])的形式来输入地图,因为对于占位符"%c",回车和空格都是一个输入,因此会导致输入的数据出错。所以在代码中凡是涉及到字符或者字符串的输入最好采用C++的输入流cin,这样可以避免很多不必要的麻烦。