油田问题

来源:互联网 发布:大型开放式网络课程 编辑:程序博客网 时间:2024/04/28 21:06

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.

输入文件包括一个或者多个图形。每个图形的第一行个告诉你接下来这个图形的高(m行)和长(n列)。如果m=0则认为文件结束。否则,1 <= m <= 100 , 1 <= n <= 100。接下来将会输入m*n大小的字符数组,一个字符表示一个区域。其中,* 表示非油田,@ 表示油田。
 

输出要求

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.
对于每个图,请输出到底有多少个连续的油田区域,注意,这个区域不会超过100个。

测试数据示例

输入

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

输出

0
1
2
2



 

















递归是栈的一种非常常见的应用,因为递归需要调用函数,函数的调用,系统将会把当前函数的执行状态暂存在系统栈里,然后再调用函数,执行完调用函数后,再从系统栈里弹出原来的函数,继续执行。这题使用了一个栈的常见应用:深度优先搜索。DFS最简单的实现,就是通过递归调用函数,对各个方向进行搜索(直到到达不可及区域停下来)。
上述油田问题,我们可以这样来理解:首先,我们要找任意一个油田所在的地方。然后,从那个地方开始,进行搜索,只要搜索到连续的油田区域,就把它填充成非油田(或者标记它,反正不要让上一步那个找任意油田的操作访问到连续的那部分。)等待那个任意油田搜索的操作结束了,那么,找到多少个,就很明白了。
好吧我猜你还没有看懂,没关系,我举个栗子:(由于*和@不是等宽字符,在这里吧*换成#)
####@
#@@#@
#@##@
@@@#@
@@##@

首先,一个双层嵌套的for循环。嗯我们找到了(0, 4)的位置有一个油田,接下来开始搜索它的连续区域(注意,斜对角也是可以的哦!)
#####
#@@##
#@###
@@@##
@@###

红色部分表示搜索到的连续区域,并且是填充成了非油田,保证那个for循环再也不会重复找它了。这时,全局计数器加1,表示找到一块区域。
然后for循环继续走,来到(1,2),嗯,又是油田,于是继续开始DFS搜索
#####
#####
#####
#####
#####

这时,全局计数器加1(即找到了两个了)。接下来,那个for循环再也不会找到油田了,于是最终油田连续区域的个数为2个。
这下明白了吧。不会很难吧。实现DFS搜索功能的那个函数的代码不是很多,也就几行而已。它是通过递归调用,把8个方向都搜索一遍(想象成一个九宫格,除了中间的它自己以外,边上的都算是连续)。



#include <stdio.h>void find(char a[][100],int x,int y);int fx[3]= {0,1,-1};int fy[3]= {1,-1,0};void find(char a[][100],int x,int y){int i,j,tx,ty;a[x][y]='*';for(i = 0;i < 3;i++){tx = x + fx[i];for(j = 0;j < 3;j++) {ty = y + fy[j];if(a[tx][ty] == '@')find(a,tx,ty);}}}int main(){char a[100][100];int i,j,m,n,p = 0,c = 0;while(~scanf("%d %d",&n,&m)){if(n == 0 && m == 0){break;}p = 0,c = 0;for(i = 0;i < n;i++){scanf("%s",a[i]);}for(i = 0; i < n; i++){for(j = 0; j < m; j++){if(a[i][j] == '@') {find(a,i,j);c++;}}}printf("%d\n",c);}}