搜索总结

搜索分为dfs(深度优先搜索)和bfs(广度优先搜索)。
简单的爆搜: 适用于数据比较小或是访问数很少的情况,一般是初学者最开始接触的。
剪枝搜索: 一般的爆搜不可行(TLE),在爆搜的基础上进行适当剪枝,有些题目需要强剪枝。这种题目难就难在如何剪枝,而不在搜的过程。一般会设置一个
限制作为预估的条件,事先打表或排序都是可采用的方式,不过最好的剪枝还是视题目的特殊性而定(说白了就是有一点贪心的思想在里面)。
启发式搜索: 需要写启发式函数,一般是预估一个极大值或是极小值,不过最好的启发式函数还是得视题目的特殊性而定,那种一眼就能看出来的很少,比赛中
肯定会以此来考脑洞(签到题除外)。
迭代加深搜索: 适用于搜索范围极大或是需要输出路径答案之类(比如在最少的步数下的一个解或是字典序最小的解之类的)
状态压缩搜索: 一般是以一个二进制数来保存状态(1,0分别代表有无之类的),有些题目需要用几位合并来表示状态,这种题目一般数据范围都很小,而且选取
某点的时候与整个状态或之前的状态等相关。
简单的单向bfs: 适合初学者刚开始接触,把状态转换写清楚即可,一般是找最短距离。有些题目还要用到优先队列。
保存路径的bfs: 最好用结构体数组模拟队列,不要用STL,保存父节点,找到解之后直接可以利用父节点回溯。
正向bfs转换为反向bfs打表: 前提是正向搜的效果跟反向搜的效果是一样的,题目中如果到达的终末状态都是一样的则可以考虑反向搜。
双向bfs:  前提是正向搜跟反向搜效果是一样的,而且一般会有步数限制,如果某一种情况无解而且单向搜会TLE的话,双向搜也会TLE,但是如果题目给了限制
步数的话而且以某种比例(一般1:1,还有2:1之类的)分能大大减少状态则可以考虑双向bfs。有些题目本身就要求双向搜。
哈希: 主要是为了将复杂的状态转换为简单的状态(一般是一个数),map也是一种哈希,使用范围比较小,很容易爆。所以还是自己手写一个哈希比较好。哈希可以
保存二三十个数合起来的状态,当然还可以更大(但是生成的状态数不能太多,否则空间时间都容易爆)。哈希是非常强大的一种方式,但是哈希只是保存状态用于去重
的一种方式,并不能用来剪枝之类的。
嵌套: dfs套dfs,bfs套dfs等,这种题目一般数据比较小,可能本身有分层,不过最重要的还是敢想。
扩大外围bfs: 一般是考虑从外围开始搜,为了方便,扩大一圈然后随便选其中一个点搜就好了。
离散化: 数据范围太大,但是点数不多,就考虑能不能先离散化再搜,有时候还得扩大2倍或是更多。
精确覆盖: 结合矩阵的一种快速搜索算法,说简单点就是选了某个点之后与之相关的某些行或者列都得删掉,模板化,难在如何构造,比赛中很少遇到。

原文地址:https://www.cnblogs.com/wust-ouyangli/p/5796922.html