很简单的一道迷宫题,我说的简单是指..地图大小 因为是固定5x5的点阵迷宫,且保证有唯一解,算是迷宫入门题吧 不过本人作为ACM小白头一次摸出这题还真是不容易啊
预处理:
就是给地图的四周“造墙”,比如把 变成 这样后面搜索时对待边界或障碍物就能共用一套逻辑, 因此5x5的地图要用7x7的数组来存储
然后就是模拟了:(貌似也可以叫做回溯?) 本人代码的大致逻辑是, 用每行3个数字的无限行数组road[][3]存储路径,前两个数字表示坐标,第三个数字表示这个坐标的“岔路口数”, (“岔路口数”是我自己起的名,表示这个点的上下左右有几个方向是可以走的,如果“岔路口数”等于2,那就是一条路的中间,如果等于1,那就是个死胡同)
我用一个整型变量direction对4取模后的值表示方向,换向逻辑是: 前方是墙时就都往右下角转向,表现为direction的值加1或减1,转向之后重复判断,如果还是不能走则重复转向,转到能走为止, 特殊地,如果右方下方都是墙,才往反方向换方向(为了避免搜索点在一个环形道绕圈)
从左上角开始往下或右走,每走出一步,在road[][3]记录当前坐标点和当前点的“岔路口数”, 若“岔路口数”等于1,说明走到了死胡同, 这时候将搜索点重置为road[][3]里上一个“岔路口数”>=3的点(我管这叫传送), 顺便将road[][3]中这个重置点的下一步所在坐标点“造个墙”,即把地图中对应点改为墙,封死死路入口, (传送之后,road数组里还留有之前行走路径,因此可得知死胡同的入口点) 之后的行走轨迹从重置点的位置开始往下覆盖, 重复以上步骤走到终点坐标为止,然后按格式输出road数组里的行走轨迹即可(逗号后面跟了一个空格)
因为在写这道题时本人还不懂DFS之类的东西,摸出来的解题逻辑和代码可能有偏复杂的地方,模板化解法回头再补充
#include<iostream>
using namespace std;
int main()
{
int maze[7][7][2] = { 0 };
for (int i = 0; i < 7; i++)
{
maze[0][i][0] = 1;
maze[i][0][0] = 1;
maze[6][i][0] = 1;
maze[i][6][0] = 1;
}
for (int down = 1; down < 6; down++)
{
for (int right = 1; right < 6; right++)
{
cin >> maze[down][right][0];
}
}
int road[3][100] = { 0 };
int down = 1, right = 1;
int direction = 4000;//0-up 1-left 2-down 3-right
int iroad = 0;
while (down != 5 || right != 5)
{
iroad++;
road[0][iroad] = down;
road[1][iroad] = right;
road[2][iroad] = 0;
if (maze[down - 1][right][0] != 1)
road[2][iroad]++;
if (maze[down][right - 1][0] != 1)
road[2][iroad]++;
if (maze[down + 1][right][0] != 1)
road[2][iroad]++;
if (maze[down][right + 1][0] != 1)
road[2][iroad]++;
if (road[2][iroad] == 1 && iroad != 1)
{
for (int i = iroad; road[2][iroad] < 3; i--)
iroad = i - 1;
down = road[0][iroad];
right = road[1][iroad];//传送到上一个岔路口
maze[road[0][iroad + 1]][road[1][iroad + 1]][0] = 1;//改地图,封死死路入口
}
if (maze[down][right][1] != 0)
{
iroad = maze[down][right][1];
down = road[0][iroad];
right = road[1][iroad];//传送到上一个岔路口
direction++;
}
else
maze[down][right][1] = iroad;
for (int i = 1; i <= 3; i++)
{
switch (direction % 4)
{
case 0:
{
if (maze[down - 1][right][0] == 1)
direction--;
}break;
case 1:
{
if (maze[down][right - 1][0] == 1)
direction++;
}break;
case 2:
{
if (maze[down + 1][right][0] == 1)
direction++;
}break;
case 3:
{
if (maze[down][right + 1][0] == 1)
direction--;
}break;
}
}
if (maze[down][right + 1][0] == 1 && maze[down + 1][right][0] == 1)
{
direction = 0;
}
switch (direction % 4)
{
case 0:down--; break;
case 1:right--; break;
case 2:down++; break;
case 3:right++; break;
}
}
for (int i = 1; i <= iroad; i++)
cout << "(" << road[0][i]-1 << ", " << road[1][i]-1 << ")" << endl;
cout << "(4, 4)";
return 0;
}