目录
剪枝(可行性&最优性)
双向搜索
迭代加深
A*算法求k优解
2SAT
. 讲义中还有一堆例题。( 原谅我真的不太想听巨佬飞跃式讲课...)
剪枝(可行性&最优性)
对于可行性剪枝,要求我们“看的越远”,剪枝的效果更好。
所谓看得更远,就是我们能够通过现在的情况,预见到若干步之后能否依然可能。
举个例子来说,比如说走棋盘问题,可行性剪枝怎么剪呢?
我们可以减掉已经出界的,这种最显然,但是效果也是最差的。
我们也可以剪掉下一步没有地方走的状态,这个相比较于上一种剪枝效果不会好太多。
但是,如果我们通过一些数学方法快速计算出来一些结果,
比如假设某种染色之后,我们现在的跳法不能跳到某种颜色了,
并且还剩余这种颜色的没有访问过,那么这种状态也是不可能到达终点的状态了。
详细说下最优性剪枝。 假设目前我们的最优解是 ans,这道题目要的是最小化答案。
- 假设到当前状态 P已经用了代价 f(P) 了,
- 假设从 P 到达终点所需的最小代价是 g(P) 的话,
- 如果 f(P) +g(P) ≥ans 则可以剪去这个状态。
由于 g(P) 是我们估出来的最小代价,那么真实代价必然不小于这个值。
那么最终的答案肯定也是要不小于当前最优解的,因此我们沿着这个状态走下去没有意义。
所以可以剪去这个状态。 最优性剪枝的重点就在于怎么去估计 g(P),
显然我们把 g(P) 估的越大, 剪去的状态就会越多,但是如果 g(P) 超过了真实代价,
就有把真正的 解剪掉的可能性,所以是不可取的。因此我们要尽量准确的估计 g(P)。
顺带一提,有的题目虽然不是最优性题目,但是我们也可以去尝试搜索最优解,
并使用最优性剪枝,有的时候能取得很好的效果。
双向搜索
双向搜索是一个比较类似于 meet in middle 的搜索技巧。
我们从起点和终点开始,同时向中间进行搜索,两侧各进行一半深度的搜索,然后进行合并。
迭代加深
思想是这样的,我们在搜索之前预先猜测选定一个答案,
然后搜索的过程中,我们采用最优化剪枝的方法。
如果预测出来的答案超过了我们预定的答案,我们就直接剪枝掉,否则继续搜索。
这种搜索方法有很多好处,如果一个题的深度优先搜索是没有上界的,
那么我们可以使用这种方法人为的固定上界,可以把一些只能 bfs 的题目改为 dfs。
其次,估价函数非常重要,我们需要尽量准确的估价函数,估价函数越准确,
我们就能得到越小的复杂度,如果有一个确切的估价函数,就可以在 O(1) 的时间内得到解。
A*算法求k优解
A* 算法是这样的,我们在宽搜的基础上,给每个状态一个估价函数,
我们每次优先拓展估价函数比较小的状态,用一个优先队列去维护。
不难发现,重点也在于估价函数,在准确的情况下,A* 算法还可以干很多的事情。
2SAT
2SAT 是这样一类问题,有 n 个 01 变量,你需要为每个变量选择一个取值,
有一些要求,形如,x1 = true||x2 = false 这样的限制。 2SAT 直接搜索显然也是 2n 的。
但是针对特殊性质,可以尝试按顺序枚举每个变量的取值,并且在确定了一个取值之和,
尝试去确定更多的取值,如果最终不产生冲突,那么中途的就都确定了,时间复杂度 O(n2)。
——时间划过风的轨迹,那个少年,还在等你。