“Red and Black(红黑瓷砖),ZOJ2165”的一种解法

一、题目

1.1题目编号:ZOJ2165

详见:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2165

1.2题目描述:

有一个长方形的房间,房间里的地面上布满了正方形的瓷砖,瓷砖要么是红色,要么是黑色。一男子站在其中一块黑色的瓷砖上。男子可以向他四周的瓷砖上移动,但不能移动到红色的瓷砖上,只能在黑色的瓷砖上移动。

本题的目的就是要编写程序,计算他在这个房间里可以到达的黑色瓷砖的数量。

 1.3输入描述

输入文件中包含多个测试数据。每个测试数据的第1 行为两个整数W和H,分别表示长方形房间里x方向和y方向上瓷砖的数目。W和H的值不超过20。接下来有H 行,每行有W个字符,每个字符代表了瓷砖的颜色,这些字符的取值及含义为:

1) '.' - 黑色的瓷砖;

2) '#' - 红色的瓷砖;

3) '@' - 表示该位置为黑色瓷砖,且一名男子站在上面,注意每个测试数据中只有一个

'@'符号。

输入文件中最后一行为两个0,代表输入文件结束。

1.4 输出描述

对输入文件中每个测试数据,输出占一行,为该男子从初始位置出发可以到达的黑色瓷砖的数目(包括他初始时所处的黑色瓷砖)。样例如下:

 

 

二、思路

由于需要求解的是从当前位置可以达到的所有黑色瓷砖的数量,显然可以利用深度搜索实现。解法比较直观,可以作为一个比较典型的DFS案例。

通过递归实现DFS的关键在于1)判定退出条件,2)施行必要的剪枝,3)确认是否需要在进入下一级递归前,从递归返回时执行必要的调整

本题比较简单,Mr. Pospro将结合代码注释进行必要的解释。

 

三、解答

/*
红与黑(Red and Black), ZOJ2165, POJ1979
2016.05.18 Wed Sunny by Pospro
详见博客 http://blog.csdn.net/pospro
*/
#include <cstdio>
#include <cstring>
#define MAXN 22

int N; //rows
int M; //columns
int cnt; //the number of ceramics he can reach;
char map[MAXN][MAXN];
int fx[8]={-1,0,0,1,1,0,0,-1}; //两个作为一组,分别表示上右下左四个方向

void DFS(int x, int y)
{
    int nextx, nexty;
    int i,j;

    map[x][y]='*'; //先把当前格设为已访问过
    for(i=0;i<8;i=i+2) //按照上右下左的顺序,朝四个方向尝试
    {
        nextx=x+fx[i];
        nexty=y+fx[i+1];

        if(nextx<0||nextx>=N||nexty<0||nexty>=M||map[nextx][nexty]!='.')
            continue; //满足以上任一个条件,则说明此路不通,换方向再试试吧

        cnt++; //如果到达这里,则说明此处也是黑瓷砖,计数加1,并启动新的搜索
        DFS(nextx, nexty);
    }
}

int main()
{
    int i,j;
    int startx, starty; //开始位置,即@所在位置
    while(1)
    {
        scanf("%d%d",&M, &N); //注意审题,题目的输入是先列后行!
        if(M==0&&N==0)
            break;
        cnt=1; //新开始,重新置1
        memset(map,0,sizeof(map)); //清空地图
        for(i=0;i<N;i++) //接收输入并找到起始位置
        {
            scanf("%s",map[i]);
            for(j=0;j<M;j++)
            {
                if(map[i][j]=='@')
                {
                    startx=i;
                    starty=j;
                }
            }
        }
        DFS(startx,starty); //启动深度搜索
        printf("%d\n",cnt);
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值