搜索专题
必备技能
- STL
- 队列
- 优先队列
那就可以了
fc(DFS&BFS)
相信大家都对搜索(深搜/款搜)有了一定程度上自己的理解了
然后据我所了解,可能大家对这两个东西的区分度可能不是特别高,然后请允许我来口胡(对比、分析?)一下这两个东西
先来一个小练习:
用搜索求斐波那契数列的第\(n\)项
可能在座的各位已经会了递推求解、矩阵快速幂求解、通项公式求解
但还是希望大家能拿起自己的草稿纸,画一画这个运行的大概的过
斐波那契数列

深度优先搜索(Depth First Search)
优势:
- 适合状态不易储存的情况
- 有时候对子问题的依赖很强
- 符合人类的思考习惯
劣势:
- 很容易超时
- 很容易爆栈
宽度优先搜索(Breadth
First Search (Baidu First Search))
优势:
- 适合状态容易储存的问题
- 不容易爆栈(搜索深度远大于\(\text{DFS}\))
- 能够将父状态继承给子状态
- 可以跑最短路啊,各种最优化问题
劣势:
- 可能产生大量的无用状态导致\(MLE\)
- 对某些数据结构的要求有点高
接下来干嘛,练题?
太没意思了吧。。。
来点有意思的?
奇技淫巧一:记忆化搜索(伪dp)
先让大家用搜索求一求
斐波那契数列
1 |
|
好像\(n\)从\(40\)开始,这两个方式跑出来的时间差距就越来越大了
咋搞?
嗯,如题:记忆化
code
1 |
|
其实这个没有什么不一样的
就是记忆化,请大家\(YY\)一下就好
来点例题?
SHOI2012滑雪
solution
那么就是用一个\(f[i][j]\)来记录在\((i,j)\)能往下滑的最大距离
那么转移的话就是 \[ f[i][j]=max(f[i-1][j], f[i+1][j],f[i][j-1],f[i][j+1])+1 \] 当然,这个方程并不完全正确,大家还需要判断一下边界条件和这个高度的大小
1 |
|
Achen
solution
手动模拟一下
会发现,其实\(A/B\)左右是否是空的,对于这道题没有本质的影响
因为要走遍所有的点的话,这只有一种方案
然后\(A/B\)的顺序对于本题也没有本质影响
来两张图?


好像就是如果\(A\)不是最靠左的点,那么\(A\)的实际位置应该是再往右走一格的位置,\(B\)也同理
那么所有的问题都可以转化为\(A,B\)分别为端点的问题了
再想,这个又能怎么考虑呢?

这啥意思?
就是到最右端点的两种方案
如果我们用一个数组\(f[i]\)来表示经过了\(i\)点左边的所有点后,最后到达\(i\)这样的情况的方案数
那么它可以写成这样\(f[i] = f[i - 1] + f[i - 3]\)
Code
1 |
|
就可以了
其实递推更简单,但是没有这个记搜快
过河卒
solution
个人觉得这是一个板子题水题
极其无脑的模拟就可以了
1 |
|
嗯,记得开\(long\;long\)我失算了,因为没开,交了三次。。。
难受。。。
奇技淫巧二:疯狂剪枝
那就是遇见不可能有贡献的答案可以直接返回
来点例题?
数的划分(加强版)
solution
我们可以先写一个暴力,康康它可以怎么记忆化
\(DFS\)的时候,我们就记录三个参数
1 |
|
记忆化一下,代码没怎么变
1 |
|
看看题解,惊艳了,这种吊打我代码神仙写法都有
当然,我将这种写法呢,只是为了让大家深刻理解一下这的记忆化搜索还有剪枝优化
奇技淫巧三:双向BFS、折半搜索
怎么说?如题!
八数码难题
solution
双向\(BFS\)嘛,对吧?
那就从首尾两端分别搜一次呗
这有什么好处呢?
简单的说,这个东西它及大幅度的剪掉了无用的状态
上图?

如果要把这个搜索树给遍历完,那么这个的时间复杂度就是\(O(2^{n+1})\)
那么如果\(n\)的数量级在\(30、40\)左右,那么恭喜你,完了!绝对\(TLE\)!
但是\(CJ\)我表示不服,我就只会搜索。。。
那么我们稍微修改一下这棵树
怎么讲?
有很多叶子节点时没有用的!!!
那么我们让这棵树有两个根,看看那些叶子结点的信息重合了
重合了就可以更新答案
那么时间复杂度?\(O(\sqrt{2^{n+1}})\),很可以!
如果原来是\(1e12\)的复杂度
根号一下就是\(1e6\),随便跑啊!!!
1 |
|
是吧,挺简单的
奇技淫巧四:IDA*
来到例题?
铁盘整理
Code
1 |
|
骑士精神
Code
1 |
|
我可能没时间写了,好网站