当前位置:首页 > 题解目录 > 正文内容

【题解】红与黑

亿万年的星光5年前 (2021-01-29)题解目录3274

【题目描述】

有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。

【输入】

包括多组数据。每组数据的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下:

1)‘.’:黑色的瓷砖;

2)‘#’:白色的瓷砖;

3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每组数据中唯一出现一次。

当在一行中读入的是两个零时,表示输入结束。

【输出】

对每组数据,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。

【输入样例】

6 9 
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
0 0

【输出样例】

45




【题目分析】


 

  1.    比较典型的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;
}


    扫描二维码推送至手机访问。

    版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

    分享给朋友:
    返回列表

    上一篇:迷宫

    下一篇:【题解】单词接龙

    相关文章

    【题解】发工资

    【题目描述】财务处的小李最近就在考虑一个问题:如果每个员工的工资额都知道,最少需要准备多少张人民币,才能在给每位员工发工资的时候都不用员工找零呢?这里假设程序猿的工资都是正整数,单位元,人民币一共有1...

    奶牛的耳语

    【题目描述】在你的养牛场,所有的奶牛都养在一排呈直线的牛栏中。一共有 n头奶牛,其中第 ii头牛在直线上所处的位置可以用一个整数坐标 pi(0<pi<10^8...

    剪刀石头布

    【题目描述】石头剪子布,是一种猜拳游戏。起源于中国,然后传到日本、朝鲜等地,随着亚欧贸易的不断发展它传到了欧洲,到了近现代逐渐风靡世界。简单明了的规则,使得石头剪子布没有任何规则漏洞可钻,单次玩法比拼...

    【题解】阳光

    【题目描述】给出一个n*n的矩阵,矩阵每个元素数值代表这个位置的阳光情况,给出正整数k,需要我们求出哪一处的k*k 区域的阳光平均值最多,阳光平均值为k*k 区域的阳光总和除于k*k。蒜头君想让我们输...

    【题解】切割钢管

    【题解】切割钢管

    【题目描述】小A是某工地的计算工程师。工地现有 n 根钢管,第 i 根钢管的长度为 ai。现在想用这 n 根钢管来做一个支撑用的柱子。我么可以切割这些钢管成为更短的钢管,但是不能缝合两根钢管。为了安全...

    【题解】剔除相关数

    【题目描述】一个数与另一个数如果含有相同数字和个数的字符,则称两数相关。现有一堆乱七八糟的整数,里面可能充满了彼此相关的数,请你用一下手段,自动地将其剔除。【输入描述】每组数据前有一个N(<10...