• bfs


    队列基本操作

    基本操作:

    push(x) 将x压入队列的末端

    pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回任何值

    front() 返回第一个元素(队顶元素)

    back() 返回最后被压入的元素(队尾元素)

    empty() 当队列为空时,返回true

    size() 返回队列的长度

     

    与深度优先搜索的对比

    深度优先搜索用栈(stack)来实现,整个过程可以想象成一个倒立的树形:
    1、把根节点压入栈中。
    2、每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中。并把这个元素记为它下一级元素的前驱。
    3、找到所要找的元素时结束程序。
    4、如果遍历整个树还没有找到,结束程序。
    广度优先搜索使用队列(queue)来实现,整个过程也可以看做一个倒立的树形:
    1、把根节点放到队列的末尾。
    2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。
    3、找到所要找的元素时结束程序。
    4、如果遍历整个树还没有找到,结束程序。

    实际应用

    BFS在求解最短路径或者最短步数上有很多的应用。
    应用最多的是在走迷宫上。
    单独写代码有点泛化,取来自九度1335闯迷宫 [3]  一例说明,并给出C++/Java的具体实现。
    在一个n*n的矩阵里走,从原点(0,0)开始走到终点(n-1,n-1),只能上下左右4个方向走,只能在给定的矩阵里走,求最短步数。n*n是01矩阵,0代表该格子没有障碍,为1表示有障碍物。
    int mazeArr[maxn][maxn]; //表示的是01矩阵
    int stepArr[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; //表示上下左右4个方向
    int visit[maxn][maxn]; //表示该点是否被访问过,防止回溯,回溯很耗时。
    核心代码。基本上所有的BFS问题都可以使用类似的代码来解决。
    structNode
    {
        intx;
        inty;
        intstep;
    Node(intx1,inty1,intstep1):x(x1),y(y1),step(step1){}
    };
    intBFS()
    {
        Nodenode(0,0,0);
        queue<Node>q;
        while(!q.empty())
            q.pop();
        q.push(node);
        while(!q.empty())
        {
            node=q.front();
            q.pop();
            if(node.x==n-1&&node.y==n-1)
            {
                return node.step;
            }
            visit[node.x][node.y]=1;
            for(int i=0;i<4;i++)
            {        
                int x=node.x+stepArr[i][0];
                int y=node.y+stepArr[i][1];
                if(x>=0&&y>=0&&x<n&&y<n&&visit[x][y]==0&&mazeArr[x][y]==0)
                {
                    visit[x][y]=1;
                    Nodenext(x,y,node.step+1);
                    q.push(next);
                }
            }
        }
        return-1;
    }

     标准模板2;

    //给一个地图由起点到点最短步数 .通*不通
    //标准广搜模版题
    #include<bits/stdc++.h>
    using namespace std;
    char mp[103][103];          //地图大小
    int vis[103][103];          //访问标记
    typedef struct point pt;    //点重命名
    struct point{int x;int y;}; //点结构体
    typedef pair<pt,int> p;     //pair存点与距离,方便队列
    int dx[4]={0,0,-1,1};       //X偏移,上下左右
    int dy[4]={1,-1,0,0};       //Y偏移,上下左右
    int main(){
        int n,m;cin>>n>>m;      //地图大小
        pt s,g;                 //定义起点与终点
        for(int i=1;i<=n;i++){  //遍历行
            for(int j=1;j<=m;j++){  //遍历列
                cin>>mp[i][j];      //输入
                if(mp[i][j]=='s'){  //如果是起点
                    s.x=i;      //记下X
                    s.y=j;      //记下Y
                }
                if(mp[i][j]=='g'){//如果是终点
                    g.x=i;      //记下X
                    g.y=j;      //记下Y
                }
    
            }
        }
        queue<p>qu;             //开队列
        qu.push(p(s,0));        //压入起点
        while(!qu.empty()){     //非空
            pt nowp=qu.front().first;   //读出队首点
            int dis=qu.front().second;  //读出队首点到起点步数
            vis[nowp.x][nowp.y]=1;      //打上已访问标记
            qu.pop();                   //弹出队首
            if(nowp.x==g.x&&nowp.y==g.y){cout<<dis<<endl;return 0;}     //到终点跳出
            for(int i=0;i<4;i++){   //未到终点则四个方向偏移
                pt newp;            //定义新点
                newp.x=nowp.x+dx[i];if(newp.x<1 || newp.x>n)continue;   //得新X,超限跳过
                newp.y=nowp.y+dy[i];if(newp.y<1 || newp.y>m)continue;   //得新Y,超限跳过
                if(vis[newp.x][newp.y]==0&&mp[newp.x][newp.y]!='*'){    //未访问且可行
                    qu.push(p(newp,dis+1));                             //新点压入队列
                }
            }
        }
        cout<<"impossible"<<endl;   //队空都走不到,就肯定走不到了
        return 0;
    }
     
  • 相关阅读:
    Python正则表达式很难?一篇文章搞定他,不是我吹!
    该用Python还是SQL?4个案例教你节省时间
    解决mysql中只能通过localhost访问不能通过ip访问的问题
    MySql按周/月/日分组统计数据的方法
    jquery清空form表单
    eclipse 创建 maven web工程
    微信授权登录
    bootstrap滑动开关插件使用
    去除编译警告@SuppressWarnings注解用法详解(转)
    dataTables添加序号和行选中框
  • 原文地址:https://www.cnblogs.com/lipu123/p/12151693.html
Copyright © 2020-2023  润新知