UVA572油藏 Oil Deposits
题目描述
某石油勘探公司正在按计划勘探地下油田资源,工作在一片长方形的地域中。他们首先将该地域划分为许多小正方形区域,然后使用探测设备分别探测每一块小正方形区域内是否有油。
含有油的地块称为油田。如果两个油田相邻,则它们是相同油藏的一部分。油藏可能非常大并且可能包含许多油田。您的工作是确定长方形的地域中包含多少不同的油藏。
输入
文件包含一个或多个网格。每个网格以包含m和n的行开始,n是数字
网格中的行和列,用一个空格隔开。如果m = 0,表示输入结束;
否则,1≤m≤100,1≤n≤100。接下来是m行,每行n个字符(不包括在内)
行尾字符)。“*” 代表没有油, “@”:表示油藏。
输出
对于每个网格,输出不同的石油储量的数量。两个不同的油藏是同一个油田的一部分,水平、垂直或对角线上相邻的油田。石油矿床将包含不超过100多个油藏。
输入样例
1 1
*
3 5
@@*
@
@@*
1 8
@@***@
5 5
****@
@@@
@**@
@@@@
@@**@
0 0
输出样例
0
1
2
2
思路分析
1.本题主要考察DFS.
如图所示:@表示油田,*代表没有油,主要统计油藏的块数,也就是图中连通分量的个数.
每个位置访问的方向有8种,如图:
算法设计如下:
判断是否出界,是否已有连通分量号或不是@’;
对字符矩阵中每个位置进行判断,如果未标记连通分量号且是’@’,则从该位置深度优先搜索;
搜索时将该位置标记连通分量号为id,从该位置出发,沿八个方向继续深度优先搜索。。
特别注意:因为有可能包含多个连通分支,因此需要从每个未标记的’@'深搜。
参考代码
#include<iostream> #include<string> #include<string.h> using namespace std; const int maxn = 105; int m, n,cnt; int setid[maxn][maxn];//标记矩阵 string arr[maxn];//存储字符的矩阵 void def(int x,int y,int id) { if (x < 0 || x >= m || y < 0 || y >= n)//判断是否越界 return; if (setid[x][y] > 0 || arr[x][y] != '@')//已有连通分量号或不是@ return; setid[x][y] = id;//做标记2 for (int i = -1; i <= 1; i++)//八个方向进行深搜. { for (int j = -1; j <= 1; j++) { if (i || j )//两者不能都为0 { def(x + i, y + j, id); } } } } int main() { while (cin >> m >> n && m && n) { cnt = 0; memset(setid, 0, sizeof(setid));//初始化 for (int i = 0; i < m; i++) { cin >> arr[i]; } for (int i = 0; i < m; i++)//防止遗漏,一个一个再次判断 { for (int j = 0; j < n; j++) { if (arr[i][j] == '@' && setid[i][j] == 0) { def(i, j, ++cnt); } } } cout << cnt << endl; } return 0; }