深搜---P1596水坑问题(C语言)

附上题目:P1596水坑

题目

由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个NxM(1<=N<=100;1<=M<=100)网格图表示。每个网格中有水('W') 或是旱地('.')。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。

[1]输入格式:

第1行:两个空格隔开的整数:N 和 M 第2行到第N+1行:每行M个字符,每个字符是'W'或'.',它们表示网格图中的一排。字符之间没有空格。

[2]输出格式:

一行:水坑的数量

[3]输入输出样例:

[4]题解:

  1. 找到连在一起的'W',找到一整块,就让计数器加1
  2. 所以要怎样找到连续的'W'呢?这里就要用到搜索,先找到一个'W之后和它有连接的都得标记
  3. 要注意自己找到过的'W'就得将它标记为不可以再算的
    要不然会计数器输出的数字会比答案大

需要注意:

这个题好像用不上回溯,一定要注意判断时需要用到哪些条件,因为这个可能会导致重复遍历,即结果会比较大:

[5]代码(带注释):

 

//前面做的搜索的题,多多少跟回溯有点关系
//但这个题好像不用,它只用遍历做相应的标记就可以了
#include<stdio.h>
int n,m;
char str[100][100]={0};
int dir[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
int way[100][100]={0};
int cout=0;
void print()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            printf("%c",str[i][j]);
        }
        printf("\n");
    }
    return;
}
void dfs(int x,int y)
{
    for(int i=0;i<8;i++)
    {
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        //不能超过边界,也不能走走过的地方
        if(nx>=0&&ny>=0&&nx<n&&ny<m&&way[nx][ny]==0&&str[nx][ny]=='W')
        {
            way[nx][ny]=1;
            dfs(nx,ny);
        }
    }
}
int main()
{
    scanf("%d %d",&n,&m);
    //吸收上面得回车符
    getchar();
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            scanf("%c",&str[i][j]);
        }
        //到下一行,会输入一个回车符
        getchar();
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            //一定要跳过被标记的地方,因为那里是在上一个水坑里面的
            //所以得跳过,开始就是这里出现了问题,导致遍历整个田地
            //得到了‘W’的数量
            if(str[i][j]=='W'&&way[i][j]==0)
            {
                //printf("%d %d\n",i,j);
                way[i][j]=1;
                dfs(i,j);
                //要注意计数器所摆放得位置,计数器没摆对位置就会导致输出得数据不是我们想要的
                cout++;
            }
        }
    }
    print();
    printf("%d\n",cout);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值