1、深度优先搜索dfs
在搜索树上的表现形式为先序遍历。
2、广度优先搜索bfs
在搜索树上的表现形式为层序遍历。
3、记忆化搜索
在某些位置需要被多次计算时,记录第一次计算的答案,后续可以省去重复计算的复杂度。
4、剪枝
搜索的瓶颈毫无疑问在于时间,合理的剪枝可以提高时效,有时候甚至可以牺牲一些正确性换取时间。
1)最优化剪枝。(不影响正确性)
面对一些最优化问题,可以用当前找出的答案作为参照,如果目前状态的取值无论如何都不可能比已找出答案优,继续搜索已经毫无意义。
2)估价函数剪枝。(不影响正确性的类型)
估价函数是个好东西,如果我们在搜索过程中中可以大致判断当前状态到末状态的大概取值,就可以结合1)最优化剪枝来判断是否该继续。
估价函数有很多种形式,具体应该根据题目的要求而定。
不影响正确性的类型,是指估价函数完全保守,其估计值必然不会超过(或低于,这里是根据题目要求而定的)实际值。
估价函数可以设计得较为复杂,但和搜索的指数或阶乘级别复杂度相比,嵌套一个估价函数的复杂度是基本上无足轻重的(能过还是能过,过不了还是过不了,当然估价函数的复杂度也要相应合理才行,搜索嵌套搜索...这辈子跑不出来)
3)判定条件优化剪枝。(不影响正确性的类型)
比如数独问题,用二进制可以将判重部分优化为O(1),可以省去搜索中若干个n。这可能效果并不明显,因为这个判定的复杂度本身就比较小。
面对一些更特殊的问题时可能会更加有效。
4)双向搜索。(不影响正确性)
这个应该归类在bfs里面,dfs说实话要实现双向还是比较...难打的。
bfs的双向搜索,从起点的终点分别出发,双方轮流拓展新的一层,直到相遇。
复杂度基本是O(√)的,具体证明这里先不贴出来,挺好证的。
5)较优解剪枝。(不影响正确性)
一些搜索题目,状态数很多,但绝大多数状态都很劣,只有少数状态较优,而使用错误的贪心可以得到其中一个比较优的解。
这里就先使用错误的贪心,获得一个较优解,用它作为基准进行最优化搜索。
根据题目的不同,这个剪枝的优化效率会很不一样。
优化的复杂度相当于所有比这个较优解劣的解的复杂度总和。
6)阈值剪枝。(影响正确性,但时间复杂度可以自行控制)
无论什么样的搜索,只要超时便是一点机会都没有的,输出一个当前答案也许就对了呢?
阈值剪枝就是设定一个计数器,在搜索将要超时时强制退出。
这时你可能已经找到了最优解,但一般情况为了求稳,还是会继续搜完其他的全部以验证自己是否是正确的。
在时间不允许的情况下,不妨赌。
但这是影响正确性的,如果数据将答案藏在比较后的状态,那这个剪枝就没用了。
7)估价函数剪枝。(影响正确性的类型)
将估价函数设计得激进(不考虑答案的完全正确性,求一个更加严格的边界)一点,优化的时间可能会更多,但对正确性可能会产生一定的影响。
这里就需要权衡利弊,自行选择,调整估价函数。
8)随机。(不影响正确性的版本)
一些对顺序没有强制要求的题目,为了防止数据刻意构造而当答案藏在后面的状态里,直接采取将原始数据随机或者随机搜索顺序的方式,将构造数据变成随机数据,取得一个随机数据下平均的复杂度。
9)随机。(影响正确性的版本)
明知使用随机可能出错,但我还是要随机,来换时间。
可以选择小范围内随机,避免正确性出现太大偏差。
以上剪枝,若干个结合起来效果更佳。
搜索剪枝就是看脑洞,你能想到哪,想到怎么剪...
搜索在面对一些正确解法并非搜索的题目时,还是要正确地去估计是否能搜索的。
原文地址:https://www.cnblogs.com/lmlysklt/p/14015042.html