也是一道极其经典的广搜题目,虽然深搜也是可以写的,但是求最优解的问题还是用广搜合适咯!
广搜问题经常使用队列(queue,deque)来实现,但这道题不行。。因为你直接把一个顶点给pop掉的话,就再也找不回来了呀!救没办法来通过指针来找回上一个节点了。
我用了一个数组来模拟队列,加以head和tail两个int表示头尾的下标。
总结一下, Bfs路径还原的关键两点:
1. 添加last保存父节点的坐标
2. 使用数组模拟队列而不是使用STL, 防止数据丢失
//迷宫问题
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
int maze[8][8];
struct Node{
int x, y, steps;
int last;//父节点
};
Node q[30]; //为防止数据丢失,使用数组模拟队列
int head = 0, tail = 0; //队列头和尾
bool visited[8][8];
int main()
{
memset(maze, -1, sizeof(maze)), memset(visited, 0, sizeof(visited));
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
scanf("%d",&maze[i][j]);
visited[0][0] = true;
int step = 0;
q[tail].x=0, q[tail].y=0, q[tail].steps=0, q[tail].last=-1; //起点入队列
tail++;
while(tail != head){
Node s = q[head++]; //取队首
if(s.x==4 && s.y==4){ //终点
stack<Node> ans; ans.push(s);
while(s.last != -1){
s = q[s.last];
ans.push(s);
}
while(!ans.empty()){
printf("(%d, %d)\n",ans.top().x, ans.top().y);
ans.pop();
}
return 0;
}
//尝试扩展s
if(s.x+1<5 && !visited[s.x+1][s.y] && maze[s.x+1][s.y]==0){
visited[s.x+1][s.y] = true;
q[tail].x= s.x+1, q[tail].y = s.y, q[tail].steps = step+1, q[tail].last = head-1;
tail++;
}
if(s.y+1<5 && !visited[s.x][s.y+1] && maze[s.x][s.y+1]==0){
visited[s.x][s.y+1] = true;
q[tail].x= s.x, q[tail].y = s.y+1, q[tail].steps = step+1, q[tail].last = head-1;
tail++;
}
if(s.x-1>=0 && !visited[s.x-1][s.y] && maze[s.x-1][s.y]==0){
visited[s.x-1][s.y] = true;
q[tail].x= s.x-1, q[tail].y = s.y, q[tail].steps = step+1, q[tail].last = head-1;
tail++;
}
if(s.y-1>=0 && !visited[s.x][s.y-1] && maze[s.x][s.y-1]==0){
visited[s.x][s.y-1] = true;
q[tail].x= s.x, q[tail].y = s.y-1, q[tail].steps = step+1, q[tail].last = head-1;
tail++;
}
}
return 0;
}