越容易用肉眼看出答案的题,用计算机越难实现。。。
人眼是面观察,而计算机是点观察。
一开始的思路就是:
一但遇到了一个内部点,也就是从这个点开始,上下左右遍历,如果四个方向都可以遇到1,那么一定就是内部点。
如果能遇到这样的点,那么直接进行递归涂色即可,非常简单。
所以难点就在于:如何高效地找出一个符合条件的点呢?
所以现在的思想:
从上到下,从左到右遍历迷宫
那么一定先遇到迷宫的左墙。
若第一次遇到1,那么直接跳到下一行,
当下一行再次遇到1的时候,开始对1后面的0进行判断,如果判断成功,那么直接停止遍历就行了,把这个找到的点,直接带入递归式,最后打印迷宫即可。
问题记录:
1.if和else if 只能进入一个,所以如果我想向四周遍历,不能是分支,只要满足条件应该都可以进入才对。
2.每次更新flag=0的值放错了位置
3.双重循环判断条件,把两个字母写重复了。
ok,现在完全没有问题,代码速度也很快!
不过代码还是很长,需要简化,学习一下大佬的思路:
利用dfs,只需要把联通块找出来就好了,让不在墙内的联通再一起就行。
只需要在迷宫外层码一圈0,然后从0,0开始深搜,遇到墙或者遇到边界或者这个点搜过了,那么就不管他了。否则,另找一个数组,把这个对应的点标为1.然后四周深搜就可以了。
这样就可以把所右的墙外点都标记上
最后没被标记的就是墙内的点,对应输出就可以了。
最牛逼的思路就在于在墙外多加上了一圈,保证连通
我的代码:
#include<stdio.h>
int maze[32][32]={0},flag=0,n=0,cnt=0,over=0;//迷宫从1到n为记录
int J_in(int x,int y);
void print(void);
void paint(int x,int y);
int main()
{
scanf("%d",&n);//读取迷宫大小
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&maze[i][j]);
}
}
//读取信息完毕
//唯一任务,找到我想要的点。
for(int i=1;i<=n;i++)//从头开始记录第一个点。
{
for(int j=1;j<=n;j++)
{
if(maze[i][j]==1&&cnt==0)//第一次遇到墙
{
cnt++;
break;//这层循环都不进行了。
// 而且cnt将会永远等于1。
}
// 现在,只要能在这里遇到1,说明是第二层了,
// 继续向后遍历,然后寻找我们需要的0
if(maze[i][j]==1)
{
flag=1;
continue;
}
else if(maze[i][j]==0&&flag==1)
{
//这一层根本没进来。。
// printf("(%d,%d),%d\n",i,j,J_in(i,j));
if(J_in(i,j))
{
// 进入这个判断说明直接结束游戏了
paint(i,j);
over=1;
break;
}
}
// 每一层循环结束之后记得
}
flag=0;
if(over)
{
break;
}
}
//测试:
print();
return 0;
}
void print(void)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",maze[i][j]);
}
printf("\n");
}
}
int J_in(int x,int y)
{
//记住不可以直接遍历x所在的一行,需要分别遍历x的左右
for(int i=y-1;i>0;i--)//x的左边
{
if(maze[x][i]==1)//如果遇到墙直接break;
{
break;
}
else if(i==1&&maze[x][i]==0)//到达边缘还不是墙
{
return 0;
}
}
//其他异曲同工
for(int i=y+1;i<=n;i++)//x的右边
{
if(maze[x][i]==1)//如果遇到墙直接break;
{
break;
}
else if(i==n&&maze[x][i]==0)//到达边缘还不是墙
{
return 0;
}
}
for(int i=x-1;i>0;i--)//点的上边
{
if(maze[i][y]==1)//如果遇到墙直接break;
{
break;
}
else if(i==1&&maze[i][y]==0)//到达边缘还不是墙
{
return 0;
}
}
for(int i=x+1;i<=n;i++)//x的右边
{
if(maze[i][y]==1)//如果遇到墙直接break;
{
break;
}
else if(i==n&&maze[i][y]==0)//到达边缘还不是墙
{
return 0;
}
}
//如果上述都符合,那么直接return 1就好了。
return 1;
}
void paint(int x,int y)
{
//上下左右遍历涂色
maze[x][y]=2;
if(maze[x-1][y]==0)
{
paint(x-1,y);
}
if(maze[x+1][y]==0)
{
paint(x+1,y);
}
if(maze[x][y-1]==0)
{
paint(x,y-1);
}
if(maze[x][y+1]==0)
{
paint(x,y+1);
}
return;
}
这篇博客探讨了一个有趣的现象,即对于人眼来说容易识别的迷宫解决方案,计算机实现起来却颇具挑战。作者通过迭代和深度优先搜索(DFS)策略,解决寻找连通块的问题。首先,从迷宫外部添加一圈0,然后从0,0位置开始,遇到墙或已搜索过的点则忽略,否则标记该点并继续搜索其相邻区域。最终未被标记的点即为墙内点,输出即可得到解决方案。博客中还详细介绍了代码实现过程及遇到的问题和改进措施。

739

被折叠的 条评论
为什么被折叠?



