zoukankan      html  css  js  c++  java
  • BFS

    BFS

    广搜及优化技巧

    一、基本算法
         如果我们把问题状态空间类比成一个图,那么广度优先搜索就相当于对这个图的广度优先遍
    历。类似地,我们依然借助一个队列来实现广度优先搜索,起初队列中仅包含起始状态,在广度
    先搜索的过程中,我们不断地从队头取出状态,对于该状态面临的所有分支,把沿着每一条分支到
    达的下一个状态(如果尚末访问过或者能够被更新成更优的解)插入队尾。重复执行上述过程直
    到队列为空

    二、模板

    struct node{
        // 你要表示的状态,例如:坐标
    }
    node _node(/*参数*/){
        node r;
        //初始化
        return r;
    }
    /*
    例如:
    struct node{
        int x,y;
    }
    node _node(int x,int y){
        node r;
        r.x=x;
        r.y=y;
        return r;
    }
    */
    queue<node>q;
    bool vis[...]...[...];//判重数组,保证每个状态只访问一次。
    void bfs(node s/*起始元素*/){
        q.push(s);
        vis[...]...[...]=1;//初始状态纪录
        while(!q.empty()){
            node head=q.front();
            q.pop();
            for(...){//遍历所有能到达的状态
                node now=_node(head...)//新状态
                if(...now...&&!vis[...]...[...]){//新状态合法且没被访问过
                    q.push(now);
                    vis[...]...[...]=1;//新状态纪录。
                }
            }
        }
    }

    【参考例题】

    1.  U68364 _GC滑迷宫

    2.  P1605 迷宫

    三、优化   

    1.双端队列BFS

        原来我们的BFS是只从队首入队,现在我们也可以从队尾入队

        举个栗子:

             我们之前已经把问题转化成一个无向图了,假设它的边权只有1和0,那么入队的时候,1从队首入队,0从队尾入队,保证队列的两段性和单调性

    【例题】   1448:【例题1】电路维修

    2.Hash判重

            深度优先搜索的另外一类应用—给出起始和目标状态,以及状态转移的规则,要求找到一条到达目标状态的路径或者方法,这类问题我们称它为路径寻找问题(例如,走迷宫问题).
            解决这类问题最有效的算法是选取合适的方法构造Hash表
            在路径寻找问题中,经常会遇到走回头路的问题,所以在搜索的过程中都必须做一件事,就是判重
            一个好的Hash 函数可以在很大程度上提高程序的整体时间效率和空间效率


    Hash表的构造方法一般有:
    ①状态压缩---运用2进制数来记录状态
    ②直接取余法---选取一个质数M作为除数
    ③平方取中法---计算关键值平方,再取中间r位形成一个大小为2^t的表
    ④折叠法---把所有字符的ASCII码加起来。

    【例题】 1449:【例题2】魔板

    3.双向宽度搜索
            从正反两个方向进行宽度优先搜索,可以大大减少搜索量,提高搜索速度
           从初始状态和目标状态两个方向同时进行扩展,如果两棵解答树在某个结点第一次发生重合,即可终止此搜索过程,则该结点所连接的两条路径所拼成的路径就是最优解

    (1)双向宽度优先搜索通常有两种搜索方法
    ①两个方向交替扩展
    ②选择结点个数较少的那个方向先扩展

          方法②只需要略加修改控制结构,每次 while循环时只扩展正反两个方向中结点数目较少的那一个,可以使两边的发展速度保持一定的平衡,从而减少总扩展结点的个数,加快搜索速度
          很明显,方法②优于方法①
    (2)算法说明
          设置两个队列q[2][maxn],分别表示正向和逆向的扩展队列
          设置两个头指针l[2]分别表示正向和逆向将扩展结点的头指针
          设置两个尾指针r[2]分别表示正向和逆向的尾指针

    【例题】  1450:【例 3】Knight Moves

  • 相关阅读:
    用python解析html--SGMLParser
    Python相对完美的URL拼接函数
    Java将视频转为缩略图--ffmpeg
    卡夫卡(kafka)
    Qt 学习之路 2
    QT的Paint 系统
    Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转
    QImage对一般图像的处理
    Hough变换-理解篇
    从零开始学习无人驾驶技术 --- 车道检测
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10995718.html
Copyright © 2011-2022 走看看