题目有问题:如何指定迷宫的起点和终点。
我这里假设迷宫某个边界位置是起点,(x, y)是否是终点要用GotGoal(x, y)函数判断。
核心函数
void DFS(char *m, int height, int width, int x, int y, int now_dir)
这里m是一个一维数组,表示迷宫。格点x, y的信息是m[y * width + x]
比如3行4列的迷宫
####
#...
..##
在m里就是#####.....##,每一行紧接着上一行。
height 迷宫高度
width 迷宫宽度
x是当前位置横坐标。右边是正方向。
y是当前位置纵坐标。下方是正方向。
now_dir是是当前的方向。你需要给上下左右4个方向规定一个编号。
比如
int dir_list[4][2] = {{-1, 0}, // 地图左
{0, -1}, // 地图上
{1, 0}, // 地图右
{0, 1} // 地图下
}
// 第一个数表示恒坐标变化量,第二个数表示纵坐标变化量
那么对于当前方向now_dir,“摸着右手边的墙”的探索方向编号依次是(可以参照上面dir_list的注释来理解)
(now_dir + 1) % 4 当前方向右侧
(now_dir + 0) % 4 当前方向
(now_dir - 1 + 4) % 4 当前方向左侧
(now_dir - 2 + 4) % 4 当前方向反方向(回头)。(这里要+4是为了防止now_dir减去数字后变成负数,负数除以4的余数还是负数)。
使用DFS的方法:
先将地图信息保存到char数组里,作为DFS函数第一参数
将迷宫入口横坐标保存到x参数,纵坐标保存到y参数
将刚进入迷宫的方向的编号(dir_list的第一下标)保存到now_dir
DFS的基本实现(伪代码)
void DFS(char *m, int height, int width, int x, int y, int now_dir){
int turn = 0
int new_dir
int new_x
int new_y
if (GotGoal(x, y) ) // 如果当前位置是终点
return
m[y * width + x] = 'X' // 占据当前位置
PrintMap(m, height, width) // 打印地图当前状态
for (turn = 1 >= -2 turn--) // 依次循环4个方向:右、前、左、回头
{
new_dir = (now_dir + turn + 4) % 4 // 计算新方向的编号
new_x = x + dir_list[new_dir][0]
new_y = y + dir_list[new_dir][1] // 计算出“如果要走新方向,则下一步的位置”
if (new_x < 0 || new_x >= width)// 如果走出左右边界
continue
if (new_y < 0 || new_y >= height) // 如果走出上下边界
continue
if ('#' == m[new_y * width + new_x]) // 如果下一步是是墙
continue
DFS(m, height, width, new_x, new_y, new_dir)
}
return
}
注意:
这个问题由于不涉及最短路,而且每走一步都算走过,包括走进了死胡同。因此这个问题完全不需要用递归,实际上程序也不可能回溯,因为每一步都是对的。直接用for或while循环就行了。用递归,当路线比较长时,可能超过 *** 作系统限制而报错。
对于有环路的迷宫,程序会死循环。
如果要判断出死循环的情况,需要一个额外的数组int m_arrived[][4],保存每个位置的每个方向是否走过。一开始都是0,走过m[i]且方向是dir的时候,m_arrived[i][dir] = 1即可。
有不明白的地方请追问。
#include<iostream>using namespace std
int map[5][5]
int vis[5][5]
struct node{
int x
int y
int pre
}edge[100]
int front=0,rear=1//队头,队尾
int dir[4][2]={{0,-1},{1,0},{0,1},{-1,0}}
void f(int i)//倒向追踪法
{
if(edge[i].pre!=-1)
{
f(edge[i].pre)
cout<<"("<<edge[i].x<<", "<<edge[i].y<<")"<<endl
}
}
void BFS(int x,int y)
{
edge[front].x=x
edge[front].y=y
edge[front].pre=-1
while(front<rear)//队列为空时终止
{
int u
for(u=0u<4u++)
{
int x=edge[front].x+dir[u][0]
int y=edge[front].y+dir[u][1]
if(x<0||x>=5||y<0||y>=5||vis[x][y]==1||map[x][y]==1)
continue
else
{
vis[x][y]=1
map[x][y]=1
edge[rear].x=x//入队
edge[rear].y=y
edge[rear].pre=front
rear++
}
if(x==4&&y==4)
f(front)
}
front++//出队
}
}
int main()
{
int i,j
for(i=0i<5i++)
{
for(j=0j<5j++)
{
cin>>map[i][j]
}
}
memset(vis,0,sizeof(vis))
cout<<"("<<"0, 0)"<<endl
BFS(0,0)
cout<<"(4, 4)"<<endl
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)