bfs算法比较高效,由于需要使用队列容器,可能会导致运行速度不太乐观
可解问题:
bfs适合解决最少步数的问题。
一维跳棋
八数码问题
迷宫最小步数
专题要点:
在使用bfs时,思考方式从节点存储的数据、边界、入队的节点(哪些节点入队)、状态压缩、状态转移、判重这几方面入手。
- 节点:bfs大多需要节点存储其所在的层数step(即步数),队首元素的step+1即为当前节点的step,然后入队。除此之外可根据题意存储坐标,序列状态,序列hash值等。
- 边界:根据题意来判断何时跳出while循环,如序列满足题目要求或是迷宫到达终点或是计数器达到一定值。
- 入队节点:即哪些节点入队,或者说队列中存储的是什么,对什么进行搜索遍历。一般要考虑与当前节点直接相连的点(有关联的点、能直接到达,直接遍历到的点),并且满足条件(在规定范围内)即可入队。
- 状态压缩:将复杂的数据压缩成简单的数据结构(降维),以方便遍历过程中的访问和修改。类似八数码问题,将3*3矩阵压缩成一维字符串或者数组进行存储。
- 状态转移:此处的状态转移是指遍历的方向和过程,如迷宫的上下左右四个方向,跳棋的左右两个格子,并将其转换为坐标的形式 ,以便进行查找访问。
- 判重:此处为入队判重而非访问判重。区别在于:
- 判重代码的位置区别:入队判重是在入队后就执行判重代码,访问判重是在访问到队首元素后再执行判重代码。
- 对bfs过程的影响:如果设置成是否已被访问,有可能在某个节点正在队列中(但还未访问)时由于其他节点可以到达它而将这个节点再次入队,导致很多节点反复入队。
因此要对已入队的结点进行标记,防止重复访问。