bfs总结

1. bfs题目的类型

对于bfs的题目一般有两种类型,第一种是已知一个棋盘,求解棋盘中某个起点到终点的最短距离,第二种是将整个棋盘看成是一个点,每一个点对应一种状态,每一个点可以进行若干种操作使得一个状态可以转化到另外一种状态,求解从起始状态到目标状态的最短距离,对于第二种属于最小步数模型,其中一个比较核心的问题是如何将状态存下来,常见的有哈希法,也即使用哈希表(c++11可以使用unordered_map来记录)来记录每一个棋盘对应的状态(一般来说记录的是字符串),python可以使用字典来记录。有的bfs题目需要记录最短路径对应的方案,如果是单向的bfs搜索那么其实还是比较好处理的,只需要记录当前状态是由哪一个状态转移过来即可,一般需要记录两个值,第一个值为到达当前状态的前一个状态,第二个值为前一个状态到当前状态的操作序列,对于python语言来说可以使用一个字典进行记录。

2. bfs的优化:双向广搜和A*算法

双向广搜:在搜索的时候从两个方向同时搜索而不是从一个起点开始搜索直到搜到终点,普通的bfs在求解的时候一直往周围进行扩展,在求解最短路模型的题目中总共遍历到的格子是非常少的所以没有什么影响,而最小步数模型一般状态空间的数量是非常庞大的,有些问题会直接达到10 ^ 15或者10 ^ 20,如果还是从一个起点开始往一个方向进行搜索那么中间遍历到的状态是非常多的,所以需要使用双向广搜进行优化,但是并不是所有的题目都可以使用双向广搜进行优化,双向广搜一般使用在最小步数模型中;双向广搜有很多种的实现方式,一般来说有两种常见的方式:① 从两个方向分别扩展一步; ② 选择当前队列中元素数量较少的一个方向进行扩展,从而到达两边平衡的效果,一般会使用第二种方式进行扩展,并且只有当两个队列都有元素的时候才进行扩展,如果一个队列中没有元素,而另外一个队列还存在元素说明起点和终点是不连通的。双向广搜的经典题目:字串变换。如果是双向广搜记录最短路径的方案感觉是比较麻烦的,因为它不像单向的bfs搜索那样只需要记录前一个状态,最后从终点开始递推到起点即可,双向广搜是从初始状态和目标状态两个方向向中间状态开始搜索直到两个搜索的方向相遇,而从终点状态到起始状态的方案其实与初始状态方向是相反的,所以当双向广搜搜索到中间状态重合的时候此时需要判断属于从起点搜索到当前这个状态还是从终点开始搜索到当前这个状态的情况,根据这两种情况决定需要翻转哪一部分的方案,可以参考179 八数码中双向广搜的写法,可以使用字典来记录对应的状态,但是记录的是从起点开始搜索或者还是从终点开始搜索到到当前状态的操作序列,这样搜索到中间状态重合的时候判断属于从哪一个方向搜索到当前状态然后根据具体的情况对方案进行翻转即可,所以这里的写法不是记录前一个状态,因为只记录前一个状态的时候需要在重合的状态判断属于哪一种情况很麻烦还不如直接记录到当前状态的操作序列然后根据对应的情况进行翻转更容易处理。

由上图可以发现从起点和终点两个方向搜索那么搜索的空间会小很多。

3. bfs,dijkstra,A*算法判重

bfs因为最先搜到的点一定是与起点距离是最小的,所以在第一次搜索到的时候最短距离就确定了,所以在入队前可以判重,每一个状态只会被更新一次,而堆优化版的dijkstra算法在入队的时候并不能确保当前入队的时候距离是最短的,每一个点可能被访问和更新多次,只有在出队的时候才可以确定当前的dis[ver]是最小的,可以在出队的时候进行判重,对于A*算法来说出队的时候不用判重,只有当终点第一次出队的时候求解的才是起点到终点的最短路径...终点第k次出队的时候那么求解的是起点到终点的第k短路。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值