一、题目
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;
}