搜索总结 - DFS&BFS&DBFS框架

16 篇文章 0 订阅

注:此博文是在老师上课之后总结的,属于课堂笔记,大部分摘自老师课件。

引言

根据“信息学初学者之家”网站的统计,Ural(俄罗斯的Ural州立大学的简称 ,有名的Ural Online Problem Set 就是该校的系统)的题目类型大概呈如下的分布:
搜索 动态规划 贪心 构造 图论
约10% 约15% 约5% 约5% 约10%
计算几何 纯数学题 数据结构 其它
约5% 约20% 约5% 约25%

搜索分类

盲目搜索:按预定的控制策略进行搜索,在搜索过程中获得的中间信息不用来改进控制策略。
1. 广度优先搜索(Breadth First Search)
2. 深度优先搜索(Depth First Search)
3. 纯随机搜索、重复式搜索、迭代加深搜索、
迭代加宽搜索、柱型搜索
启发式搜索:在搜索中加入了与问题有关的启发性信息,用以指导搜索朝着最有希望的方向发展,加速问题的求解过程并找到最优解。
1. A*算法
2. IDA*算法

深搜DFS与回溯法与广搜辨析

概念

深搜即深度优先搜索,总结一句话是不撞南山不回头。就是搜索按一定限制条件,往深处搜索,直到不能此路不能搜索再换路,直到所有部分全搜索完。
回溯法又叫试探法,我觉得他和深搜类似,不过,回溯一般是用栈的形式,记录每次每一步,不满足前进的步就退回(即出栈),这种走不通就退回再走的技术为回溯法。
广搜即广度优先搜索,就是按层次搜索,一层层来,但是顺序是有要求的,就是上一层按什么顺序搜索,下一层也要按这个顺序层次搜索。
话不多说,看下图搜索的箭头方向,方便记忆。

深搜与广搜区别

  • 相同点:都是对于树状的搜索树进行,都可判定解的存在性和总数。属于粗放型的搜索,接近于暴力解决。
  • 不同点:
    • 深度优先搜索:利用这种数据结构来实现(利用递归便于实现,但是效率较低),找到的第一个解不一定是最优解,只是先序遍历最早的可行解
    • 广度优先搜索:利用队列这种数据结构来实现,找到的第一个解经常都是最优解(如迷宫的最短路径),但是不常用来求所有解(重复的次优解常常都被剪枝剪掉了)。

DFS代码基本框架

递归

void DFS(int k)  //处理第k步
{
    if(k==n)   //已经处理到第n步,到达目的状态  
           输出结果
    else{//处理第k步
          for (int i=1; i<=m; i++)  //第k步中有m种可能
          { 
               处理第k步 
                      DFS(k+1);//进入第k+1步
          }
    }
}

非递归

//定义一个栈;
//起始点加入栈;
while(栈不空)
{
    //取出栈顶结点;
    //若它是所求的目标状态,跳出循环;
    //否则,从它扩展出子结点,全都添到栈顶;
}
//若循环中找到目标,输出结果;
//否则输出无解;

BFS代码基本框架

  • BFS关键问题:判重。
  • BFS主要试用于搜索最短距离,即逐层平行搜索。
void BFS()
{
    //初始化队列
    while(队列不为空且未找到目标节点)
    {
        //取队首节点扩展,并将扩展出的节点放入队尾;
        //必要时要记住每个节点的父节点;
    }
}

拓展之(DBFS)双向广度优先搜索

  • DBFS算法是对BFS算法的一种扩展。
  • 案例见:Knight Moves
  • DBFS算法从两个方向以广度优先的顺序同时扩展,一个是从起始节点开始扩展,另一个是从目的节点扩展,直到一个扩展队列中出现另外一个队列中已经扩展的节点,也就相当于两个扩展方向出现了交点,那么可以认为我们找到了一条路径。即是起点和终点同时出发,逐层推进,相遇时,将两个方向走的步伐相加。
  • 注意要交替逐层搜索,要先检查该方向该层所有结点再交替。
//双向广搜代码框架
struct State {}; //状态
queue<State>que[2];
bool flag;
void bfs(int d) {
    //取队首节点扩展
    State p=que[d].front();que[d].pop();
    if(p==goal) flag=true;
    else{//将扩展出的节点放入队尾;
        //必要时要记住每个节点的父节点;
        State q;//新结点
        //...新结点的拓展处理
        que[d].push(q);//新状态入队
    }
}
int dbfs() {
    //初始化
    int cnt=0;
    while(flag) {
        cnt=que[0].size();
        while(cnt-- &&flag)
            bfs(0);
        cnt=que[1].size();
        while(cnt-- &&flag)
            bfs(1);
    }
    return cnt;
}

最终笔记于2017-6-4;
二次笔记于2017-07-17;
三次笔记于2017-07-27。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值