模拟退火 (Simulate Anneal,SA) 是一种随机化算法。和爬山法不一样的地方在于拥有一个跳出去的概率以避免陷入局部最优解的情况。
模拟退火
从维基借一张图
随着最优解的接近,全局最优解逐渐稳定下来。
过程
对于平衡点 / 吊打 XXX这道题,我们以坐标平均值作为初始点。
根据当前点随机出一个新的解,如果它更接近最优解就接受它(即更新全局最优解)
如果不满足接近最优解的条件,就以一定的概率接受这个解。
概率的计算公式:设当前点与最优解的差为 ΔE,当前温度为 T,则这个概率为 ekTΔE。
其中 k 为一个随机数。在 C++ 中,计算 ek 的函数为 exp(k)
。
先从初始温度 T0 开始,每次降温时让当前温度 T=T⋅Δ,其中 Δ 是一个略小于 1 的数。显然 Δ 越小降温幅度越大,得到最优解的概率越小,但运行的时间也最短。
设定一个终止温度 Tk,当 T>Tk 时降温。
关于调参
要先设定随机数种子。(srand()
函数)这个随机数种子在一定程度上决定您是否能够 AC 这道题。
建议多跑几遍模拟退火过程以获得最优解。
可以调大 Δ 的值以小幅度降温,获得最优解的概率也越高。(相应地,运行时间会变长)
技巧
在时间限制内多跑几遍模拟退火。其中 TIME_LIMIT
是自定义的一个常数。
clock()
函数能够返回程序已运行的时间,可以利用这个东西卡时限。
代码与注释