目录
题目描述
在本题中给定一个方形区域,在区域内有 w(wall) 和 l(land) 两个形式的字符,现需要你编写一个程序将该区域内所有的联通的l小室找出来。联通的小室指的是该区域内的所有字符可以通过上下和左右的行走到达,而不会撞到墙(wall)。
输入输出格式
输入格式
第一行有两个整数 m, n
,表示数组方形区域的长宽(m
表示行数,n
表示列数); 第二行按照上一行的输入,对方形区域进行输入,该区域只会包含w
和l
两种字符。
输出格式
一行输出数据,表示该连通区域具有多少个独立的连通小室。
输入输出样例1
输入
3 3
w w w
w w w
w w w
输出
0
输入输出样例2
输入
10 10
wllwlwlwlw
lwlwllwlww
lwlwwlwllw
lwwlwwlwll
llwlwllwwl
llllllllwl
wwwlwlwllw
wlwwlwlllw
lwwllwllww
wllwlwllwl
输出
11
我想说的话:这题的输入很讨厌,地图的形式有时候会有空白符,有时候又没有空白符,C语言在这里输入挺麻烦的,我也是搜了好多资料,最终总结出一个道理:“基础不牢,地动山摇”。为了写这题,我恶补了好多知识点,太痛苦了。
这题我用两种方法写,DFS和BFS。先将放正确答案,后面会有错误写法以及如何解决这个问题和相关知识点(ps:第一次写博客,不太会编辑)
DFS代码:
#include <stdio.h>
char map[200][200];
int m,n,ans=0;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};//上下左右走
void dfs(int x,int y)
{
map[x][y]='w';//走过后就标记为墙,下次不在访问
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx<0||ny<0||nx==m||ny==n||map[nx][ny]=='w')//看是否出界以及是不是墙
continue;
dfs(nx,ny);
}
}
int main()
{
scanf("%d%d",&m,&n);
getchar();//一定要清除缓冲区!!!!
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]==' ')//消除题目给的实例中空白符的影响
{
j--;//重新赋值,这里c++是没这个烦恼的,不过我没学c++
}
}
getchar();//这个也是清除缓冲区
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(map[i][j]=='l')
{
ans++;
dfs(i,j);
}
}
}
printf("%d",ans);
}
BFS代码:
#include <stdio.h>
char map[200][200];
int m,n,ans=0,que[200][3];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};//上下左右走
void bfs(int x,int y)
{
ans++;//几个队列
int nx,ny;
int t=0,w=1;//队首队尾指针
que[1][1]=x;
que[1][2]=y;//初始节点入队
map[x][y]='w';
while(t<w)//如果队列非空就继续循环
{
t++;
for(int i=0;i<4;i++)
{
nx=que[t][1]+dx[i];
ny=que[t][2]+dy[i];
if(nx<0||ny<0||nx==m||ny==n||map[nx][ny]=='w')//看是否出界以及是不是墙
continue;
else{
w++;//尾指针+1
que[w][1]=nx;
que[w][2]=ny;//新结点入队
map[nx][ny]='w';
}
}
}
}
int main()
{
scanf("%d%d",&m,&n);
getchar();//一定要清除缓冲区!!!!
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]==' ')//消除题目给的实例中空白符的影响
{
j--;//重新赋值,这里c++是没这个烦恼的,不过我没学c++
}
}
getchar();//这个也是清除缓冲区
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(map[i][j]=='l')
bfs(i,j);
}
}
printf("%d",ans);
}
错误赋值1:
scanf("%d%d",&m,&n);
getchar();
for(int i=0;i<m;i++)
{
gets(map[i]);
}
这个我验证的时候也是空白符的原因,不过我没有尝试加 if 语句排除空白符的干扰,你们可以尝试一下哟。
错误赋值2:
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%c",&map[i][j]);
}
}
这个错因就很杂了,未清除缓冲区,未排除空白符的影响。
错误赋值3:
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
scanf("%s",&map[i][j]);
}
%s以空白符作为分割
scanf的注意事项:
对于 %c 类型的输入,scanf 把空白符也会当成要接收的字符,在本题中就是会占用一个数组位置,所以我写了一个if条件语句排除空白符的影响,我觉得这是最简单的消除影响的办法了,其他的我找了好久或多多少都有点麻烦,然后就是\n的影响,最简单的就是清除缓冲区,直接写个getchar(),不加会影响后续的赋值。(具体细节大家可以搜搜其他的资料)
一般来说如果有连续 scanf 的情况要考虑加上getchar(),其实我一开始写的是%s,因为 %s 针对空白符好像不像 %c 那样,%s 遇到空白符就停止输入了,也不会有回车符的影响,但本题又是以空白符作为分割的,所以遇上实例2那样的输入就没办法的,这就是这道题让我讨厌的点!!!是真的好讨厌,为了解决这个问题,我搜了好久好久好久,不过还好最后我解决了。
本题我还试了gets(),指针,奈何能力不够,都没成功。
结语
其实我感觉我写的DFS和BFS差别不大,欢迎各位大佬斧正我的错误。
唉,基础不牢,地动山摇。