• 信息学奥赛一本通网站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:上面说的"神奇的东西"其实我也很难解释,大家想不明白可以画个图理解一下

  • 相关阅读:
    layer备忘
    Java中遍历Map对象的4种方法
    为什么Java中1000==1000为false而100==100为true?
    linux系统安装psycopg2
    centos7源码安装mysql5.7
    Azure Sql
    javascript和jQuery动态修改css样式的方法
    Git early EOF index-pack failed 问题
    C# 多线程——SemaphoreSlim的使用
    Docker 可视化
  • 原文地址:https://www.cnblogs.com/lztzs/p/10736569.html
Copyright © 2020-2023  润新知