【题解】红与黑
【题目描述】
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
【输入】
包括多组数据。每组数据的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下:
1)‘.’:黑色的瓷砖;
2)‘#’:白色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每组数据中唯一出现一次。
当在一行中读入的是两个零时,表示输入结束。
【输出】
对每组数据,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。
【输入样例】
6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 0 0
【输出样例】
45
【题目分析】
比较典型的dfs算法,跟走迷宫类似,因为是字符操作,所以可以再做输入的时候可以先转换成数字(不转换也可以)。
2.当我们处在一个点时,有四种不同的走法(上、下、左、右),可以单独判断,也可以写一个数组简化来判断。
3.比较容易忽略的一点是w和h分别代表x和y方向,如下图:
这个图是我们常见的矩阵,x不断变化的方向是x方向,y不断变化的方向是y方向。回想一下我们输入二维数组的过程,是先输入的y方向,在输入的x方向,也就这个题目描述的是相反的。(这个是大多数人忽略并且失分的点)
4.最好在输入过程把起始点的位置保存下来,我们从起始点开始深搜。
5.最后这个输入0,0要么就是没有太大意义,因为行和列都已经固定了。要么就是给的行和列没有意义,需要最后的输入完了0,再来判断实际的行和列。
6.当我们在地图上走的时候,每走过一个点就要标记一下这个点,我们可以用flag数组标记。
【参考答案1】
#include<iostream> #include<cstdio> using namespace std; int w,h; // 按照题目要求,w代表x方向(列),h代表y方向(行) int x,y; //保留每次起始点的位置 int sum=1; //用来计数的,初始值是1 char map[25][25]; //地图数组 char flag[25][25]; //标记数组,用来表示走过的路 void dfs(int i,int j){ flag[i][j]='#' ; //把每一轮走过的路都用flag数组标记一下。 if(map[i-1][j]=='.' && flag[i-1][j] !='#') //从上方开始判断 { sum++; dfs(i-1,j); //继续上一个位置 } if(map[i+1][j]=='.' && flag[i+1][j] !='#') //下方 { sum++; dfs(i+1,j); } if(map[i][j-1]=='.' && flag[i][j-1] !='#') //左侧 { sum++; dfs(i,j-1); } if(map[i][j+1]=='.' && flag[i][j+1] !='#') //右侧 { sum++; dfs(i,j+1); } return ; //如果上面四种情况都不成立,就回溯到上一步。 } int main() { scanf("%d%d",&w,&h); for(int i=1; i<=h; i++) //反着录入,保证行和列是正常的 for(int j=1; j<=w; j++) { cin>>map[i][j]; if(map[i][j]=='@') { //如果是起始点,就记录下来 x=i; y=j; } } dfs(x,y);// 从起始点坐标开始寻找 cout<<sum<<endl; //输出最后结果 return 0; }
【参考答案2】
也可以参考下面的代码,因为只有4个方向,所以循环四次就行,
#include<iostream> using namespace std; int n,m; int step=0; char map[30][30]; //用来记录黑白瓷砖 bool visit[30][30]; //用来记录是否走过 int tr[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //定义一个数组来表示每一个位置可以进行的尝试 bool in(int x,int y) //bool型变量判断是否还在规定区域内 { return 0<=x&&x<n&&0<=y&&y<n; } void dfs(int x,int y) //最重要的部分 深搜 { step++; //用step表示可以走到的砖块数 visit[x][y]=1; //走过的地方记录在 visit中 防止重复 for(int i=0;i<4;i++) //每一个位置都尝试四种可能 { int tx=x+tr[i][0]; int ty=y+tr[i][1]; if(!visit[tx][ty]&&map[tx][ty]=='.'&&in(tx,ty)) /*判断每一种可能是否符合要求 (1.未走过 2.是可以走的黑(or红)砖 3.是否还在规定区域内)*/ { dfs(tx,ty); } } } int main() { cin>>m>>n; //m代表x方向(也就是列) n代表y方向(也就是行) int x,y; for(int i=0;i<n;i++) //输入n*m矩阵 for(int j=0;j<m;j++) { cin>>map[i][j]; if(map[i][j]=='@') //判断初始位置 并将其行和列位置赋给x,y记录 { x=i; y=j; } } dfs(x,y); //深搜 cout<<step; return 0; }
(adsbygoogle = window.adsbygoogle || []).push({});