Oil Deposits

Oil Deposits

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 42755 Accepted Submission(s): 24808

Problem Description
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.

Input
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 an oil pocket.

Output
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.

Sample Input
1 1
*
3 5
@@*
@
@@*
1 8
@@**@*
5 5
**@
@@@
@*@
@@@*@
@@**@
0 0

Sample Output
0
1
2
2
题意分析

给出地图规模n * m,地图中 *(星号)代表空白, @ 代表油田。一群@联通在一起称为油田块(此处的联通为八方向联通)。求地图中油田块的个数。

分析:
既然是求解油田块的个数,自然先想到的办法就是先处理一个油田块,然后处理下一个油田块……然后依次计数油田块的个数,也就是每次处理一个油田块的时候+1。我们按照这种方法来实现。
与之前的选数字,或者是给出指定入口求解是否能走地图的题目不同。本题需要全部遍历地图,也就是说需要一个一个格子来遍历地图,采用双重的for循环来实现。试想一下:当某一个格子是@时候,我们就从这个格子开始进行dfs,dfs的目的是处理掉与@相连的所有的@,于此同时计数+1。处理完成后,找到下一个是@的格子,再处理掉与此相连的@,计数+1。如此往复,直到处理完整个地图,搜索结束。
那么不难看出,

*递归边界就是:这个格子在地图外边。进行递归的条件是:当且仅当这个格子是@并且还没有访问过。
———————————————*

还有一点别忘记,此题判定@@相邻的条件是八向联通 也就是左上左下右上右下相邻也算联通,所以此题是八向搜素。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,visit[105][105],cnt;
//int spx[]={0,1,0,-1,1,1,-1,-1};
//int spy[]={1,0,-1,0,-1,1,1,-1};
int xy[8][2]={{0,1},{0,-1},{1,0},{-1,0},{1,-1},{1,1},{-1,-1},{-1,1}};
char mp[105][105];
bool check(int x,int y)
{
    if(x<0||y<0||x>=n||y>=m)
    return false;
    else
    return true;    
}
void dfs(int x,int y)
{
    if(!check(x,y)) return;//发生越界的时候终止递归
    visit[x][y]=1;
    for(int i=0;i<8;i++){
        int nx=x+xy[i][0];
        int ny=y+xy[i][1];
        if(visit[nx][ny]==0&&mp[nx][ny]=='@')//当且仅当格子是@并且没有被访问过 
        dfs(nx,ny); 
    } 
}
int main()
{
    while(scanf("%d %d",&n,&m)&&n){
        for(int i=0;i<n;i++)
        scanf("%s",mp[i]);
        cnt=0;
        memset(visit,0,sizeof(visit));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++)
            {
                if(visit[i][j]==0&&mp[i][j]=='@')
                {
                    cnt++;
                    dfs(i,j);
                }
            }
        }
        printf("%d\n",cnt); 
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值