信息学奥赛一本通网站1255 迷宫问题 题解

今天做了一道广搜题目[我是传送门],还是老套的迷宫问题.

但是这个是需要记录路径,我之前也听说过这种题目,不过这是第一次做.

其实我一开始想了很长时间,想了很多实现不了的思路,不过我翻课本的时候

算了,不"虚伪"了,直接进入正题:

和普通的迷宫问题唯一的区别的需要记录路径,基本相当于"升级",我们可以定义一个数组pre[]来记录前驱或后继(本体显然是后继)

但本蒟蒻一开始想错了,写成了前驱,但是我很聪(lan)明(duo),写了一个stack,又倒过来一遍,大家凑活着看吧(大家看明白后可以自己写后继):

#include<bits/stdc++.h>
using namespace std;
int tot[5][5];
struct P {//定义结构体,因为是二维的,所以需要一个x一个y
    int x;//前驱横坐标
    int y;//前驱纵坐标
};
P pre[5][5];int xx[5] = {0,-1,0,0,1},yy[5] = {0,0,-1,1,0 };//神奇的东西,一会就明白(之前用过的话当我没说)
int a[5][5];//二维空间
queue<int>q;//广搜用的队列
stack <int> s;//偷懒用的栈
void print(int x2,int y2) {//打印
    if(x2 == 0 && y2 == 0) {//如果存完了
        while(s.empty() == 0) {//开始弹出
            int a = s.top();//一定要定义一个a不然会反过来(写前驱的话)
            s.pop();
            cout<<"("<<s.top()<<", ";
            s.pop();
            cout<<a<<")"<<endl;
        }
        cout<<"("<<4<<", "<<4<<")"<<endl;
        exit(0);
    }
    int x3=pre[x2][y2].x,y3=pre[x2][y2].y;//没存完就递归存数(可以改循环)
    s.push(x3);
    s.push(y3);
    print(x3,y3);//递归
}
void gs() {//广搜(看名字就能看出来我才不用什么BFs当名字,花里胡哨的) while(q.empty() == 0) { int x = q.front();//这里可以用两个队列一个存x一个存y,但我喜欢这样 q.pop(); int y = q.front(); q.pop(); for(int i=1; i<=4; i++) {//神奇的搜索,自己悟 int x2 = x + xx[i];//新节点的横坐标 int y2 = y + yy[i];//纵坐标 if(a[x2][y2] == 0 && x2 >= 0 && y2 >= 0 && x2 < 5 && y2 < 5) {//如果没搜过且不越界 q.push(x2);//存入 q.push(y2); tot[x2][y2] = tot[x][y] + 1;//每一个节点都是由他的上一个节点扩展,所以是上一个+1; a[x2][y2] = 1;//标记 if(pre[x2][y2].x == 0) {//如果是第一次搜 pre[x2][y2].x = x;//记录 pre[x2][y2].y = y; } } if(x2 == 4 && y2 == 4) {//到达终点 print(4,4);//打印 return ;//结束 } } } } int main() { for(int i=0; i<5; i++) {//输入 for(int j=0; j<5; j++) cin>>a[i][j]; } q.push(0);//以(0,0)为起点开始 q.push(0); gs();//搜索 return 0; }

这其实也是一个广搜问题模板(自己写的,可能不正规不如其他好),其他广搜也可以用这个当模板

ps:上面说的"神奇的东西"其实我也很难解释,大家想不明白可以画个图理解一下

猜你喜欢

转载自www.cnblogs.com/lztzs/p/10736569.html
今日推荐