Oil Deposits(DFS)

Oil Deposits
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
 
Practice
 
HDU 1241
Description
GeoSurvComp地质调查公司负责探测地下石油储藏。 GeoSurvComp现在在一块矩形区域探测石油,并把这个大区域分成了很多小块。他们通过专业设备,来分析每个小块中是否蕴藏石油。如果这些蕴藏石油的小方格相邻,那么他们被认为是同一油藏的一部分。在这块矩形区域,可能有很多油藏。你的任务是确定有多少不同的油藏。

Input
输入可能有多个矩形区域(即可能有多组测试)。每个矩形区域的起始行包含m和n,表示行和列的数量,1<=n,m<=100,如果m =0表示输入的结束,接下来是n行,每行m个字符。每个字符对应一个小方格,并且要么是'*',代表没有油,要么是'@',表示有油。

Output
对于每一个矩形区域,输出油藏的数量。两个小方格是相邻的,当且仅当他们水平或者垂直或者对角线相邻(即8个方向)。


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


大笑大笑大笑比较基础的DFS搜索题

得意方法一:

//AC...DFS堆栈写法
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;


int mark[110][110];
int Move[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
char str[110][110];
int n,m;
struct data
{
    int x;
    int y;
};


void dfs(int x,int y)
{
    stack<data> stk;
    data t,tt;
    t.x=x;
    t.y=y;
    stk.push(t);
    while (!stk.empty())
    {
        t=stk.top();
        if (mark[t.x][t.y])
            stk.pop();
        else
        {
            mark[t.x][t.y]=1;
            for (int i=0;i<8;i++)
            {
                tt.x=Move[i][0]+t.x;
                tt.y=Move[i][1]+t.y;
                if (tt.x<0||tt.y<0||tt.x>=n||tt.y>=m)
                    continue;
                if (!mark[tt.x][tt.y]&&str[tt.x][tt.y]=='@')
                    stk.push(tt);
            }
        }
    }
}


int main()
{
    while (scanf("%d%d",&n,&m)&&n&&m)
    {
        int num=0;
        memset(mark,0,sizeof(mark));
        for (int i=0;i<n;i++)
            for (int j=0;j<m;j++)
                scanf(" %c",&str[i][j]);
        for (int i=0;i<n;i++)
        {
            for (int j=0;j<m;j++)
            {
                if (str[i][j]=='@'&&!mark[i][j])
                {
                    ++num;
                    dfs(i,j);
                }
            }
        }
        printf("%d\n",num);
    }
    return 0;
}


得意方法二:

//AC...DFS递归写法
#include<cstdio>
#include<cstring>


int mark[110][110];
int Move[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
char str[110][110];
int n,m;
struct data
{
    int x;
    int y;
};


void dfs(int x,int y)
{
    int xx,yy;
    if (mark[x][y])
        return ;
    else
    {
        mark[x][y]=1;
        for (int i=0;i<8;i++)
        {
            xx=x+Move[i][0];
            yy=y+Move[i][1];
            if (xx<0||yy<0||xx>=n||yy>=m)
                continue;
            if (!mark[xx][yy]&&str[xx][yy]=='@')
                dfs(xx,yy);
        }
    }
}


int main()
{
    while (scanf("%d%d",&n,&m)&&n&&m)
    {
        memset(mark,0,sizeof(mark));
        int num=0;
        for (int i=0;i<n;i++)
            for (int j=0;j<m;j++)
                scanf(" %c",&str[i][j]);
        for (int i=0;i<n;i++)
        {
            for (int j=0;j<m;j++)
            {
                if (str[i][j]=='@'&&!mark[i][j])
                {
                    num++;
                    dfs(i,j);
                }
            }
        }
        printf("%d\n",num);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值