随机算法
随机化算法
基本分析
Union Bound
即:
Markov 不等式
若
Example(Max-Cut算法)
一个无向无权图,将点集划分成两个部分,使得跨越这两部分的边尽可能多.
直接随机划分,容易见到每条边有
由此立即见到,
由于每次独立操作,因此如果有
Chernoff Bound
设
Example(Median Trick)
现在有一个黑盒能够以
考虑重复
Chernoff Bound 告诉我们
Hoeffding 不等式
设独立随机变量
编程中的随机性
一般采用伪随机,也即是给定初值
数值概率算法
即通过随机选取元素从而求得在数值上的近似解.较之于传统算法,其运行速度更快,而且随着运行时间的增加,近似解的精度也会提高.在不可能或不必要求出问题的精确解时,可以使用其得到相当满意的近似解,如随机撒点法(近似求难以计算的图形面积).
Monte Carlo算法
总是能在确定的运行时间内出解,但是得到的解有一定概率是错的.通常出错的概率比较小,因此可以通过反复运行算法来得到可以接受的正确率.
求解最优化问题的Monte Carlo算法
事实上,大部分最优化问题都可以转化为判定性问题:也就是判定一个解是否是最优解,因此我们接下来基本都是讨论的求解判定性问题的Monte Carlo算法.
求解判定性问题的Monte Carlo算法
-
假倾向的Monte Carlo算法:当这类算法的返回值为假的时候,结果一定正确,但返回值为真的时候则有一定概率错误.
-
真倾向的Monte Carlo算法:当这类算法的返回值为真的时候,结果一定正确,但返回值为假的时候则有一定概率错误.
-
产生双侧错误的Monte Carlo算法:无论返回值为什么都有概率出错.基本不会使用.
以下讨论的Monte Carlo算法均为产生单侧错误的Monte Carlo算法.
正确率与复杂度
显然,如果我们有一个单词正确率为
算法设计思路1
我们来总结一下通常的Monte Carlo算法的设计思路:
设计一个能解决问题的确定性算法
-
这个算法需要枚举一些元素.
-
设这个算法的复杂度为
,其中 为枚举部分的复杂度, 为单词枚举中计算所需的复杂度.大部分情况下应保证 不会很大.
向算法引入随机化优化复杂度
-
随机化寻找元素来降低复杂度.
-
计算随机化情况下的正确率以及复杂度.
算法设计思路2
设计一个能解决问题的确定性算法
-
这个算法需要用到一个或多个传入的元素.
-
这个元素的值不应该依赖于输入数据.
-
我们可以通过check这个元素来得到与答案有关的信息.
向算法引入随机化优化复杂度
-
随机这个元素.
-
计算随机化情况下的正确率以及复杂度
Example
Example 1(Millar-Rabin算法)
略
Example2(CodeChef MSTONE)
平面上有
考虑一个朴素的暴力:枚举两个点,确定一条直线,然后判断多少个点在这条直线上.但是这样复杂度是
考虑加入随机化.我们不妨每次随机两个点,注意到存在七条直线覆盖全部的点,那覆盖点最多的直线覆盖的点数一定不少于
Example3(CF364D Ghd)
给定一个长度为
注意到我们随机一个数,这个数在最终答案中的概率是
冷静一下,我们不妨将这
Example4([POI2014]Couriers)
给定长度为
先存下来每个位置的数是第几次出现,我们就可以利用二分快速找到一个区间内某个数出现次数.接下来只需要随机化找这个区间内某个数并判断是否满足条件即可.
Example5([NOI2013] 向量内积)
先考虑
首先,我们自然可以枚举一个向量
冷静一下,这个过程其实就是一个矩阵乘法的过程:我们设
这咋做啊?我们冷静一下,构造一个矩阵
这咋办呢?我们考虑这么一点:如果
接下来,我们要证明其正确率上的合理性.这个算法显然是单侧错误的Monte Carlo算法.问题在于正确率:
令
至于找到答案:我们找到一个不为
Las Vegas算法(Sherwood算法)
总是能返回正确的结果,但是其运行时间不确定.对于一些平均时间复杂度优秀,但是最坏情况下复杂度较高的确定性算法,通过引入随机函数,尝试减小最坏情况的可能性,以在期望意义下达到优秀的时间复杂度.
算法设计思路
设计一个能解决问题的确定性算法
-
这个算法需要枚举全排列.
-
通常,问题问的是要么只是可行解而不是最优解,要么最优方案特别多,总之要保证有用的排列个数不会太少
向算法引入随机化优化复杂度
-
随机化寻找排列来降低复杂度.
-
通常证明复杂度和正确率巨大麻烦,这里建议直接实践证明.
Example
快速排序算法
我们试图计算它的期望时间复杂度:
不妨设
做放缩(可能有些地方需要
由于
因此:
我们要证明
于是显然存在,假设成立.
一类由Monte Carlo算法改造而成的算法
对于一类一定有解的构造性问题,假设我们有一个正确率为
设其期望运行
则期望复杂度为
Example3(CF329C Graph Reconstruction)
Example4([Petrozavodsk Summer-2015. Moscow IPT Contest B]Game With A Fairy)
首先注意到一个问题:操作能得到的信息太少了,应该是没有什么确定性算法.因此考虑随机化,那就肯定要先将整个序列random_shuffle一下.
然后呢?我们考虑之后随机选取新序列的一个前缀询问,只要有大致的正确性/复杂性估计应该就是很正确的.
这里有一种方式:考虑这个前缀中第一个有宝藏的位置
考虑因为是随机,所以
爬山与模拟退火
爬山
也就是随机一个起始的解,然后走向与其相邻的较大的解.
但是这样会卡在一个局部最优解上而得不到全局最优解.
于是我们就有了模拟退火算法.
模拟退火
简而言之,模拟退火就是以一定的概率跳到随机的不优秀的点,这样就避免卡在了局部最优解上.不妨设我们想找到最大解,如果要最小解那就稍微改改.
下面给出这个概率的公式:
具体流程是,先设定一个初始温度
数据随机下的性质
树
-
随机树树高为
. -
点的度数期望为
.
数
- 数字的期望因数个数为
.
序列
- 随机序列的LIS长度期望为
.
评论