模拟退火

核心思路就是模拟物理上的退火过程,有一个初温和末温,和降温系数(每次初温乘以系数),当初温大于末温时,我们随机一个解,并尝试更新当前解,当不大于末温时退火结束。

更新的方法:

如果新解严格优于当前解,直接更新。如果劣于,以一定的概率接受新解,一定的概率不接受,且新解越劣、当前温度越低更新新解的概率越低。

trick:

记录过程解的最优解,然后多跑几次退火,每次退火可以从当前最优解开始跑。

对于可以合法划分的问题,尝试化成几个相同的小子问题,然后对于每部分退火并合并。

调大初始温度,调小末温,使降温系数趋近于1(注意别太接近了炸精度,一般最多到 0.999 就极限了,再多就炸了)。

对于非提交答案题,为在有限时间内跑解,可以卡时,以时限 1s 为例,可以 while((double)clock() / CLOCKS_PER_SEC < 0.95)SA(); 。当然,这样的话要保证一次 SA() 的时间小于 0.05s。

然后对于是否接受新解,只需记住:if(exp(-del / ts) * RAND_MAX > rand())update(); 其中 del 是需要大于 0 的,表示新解劣于原解的程度。

例1:P2538

例2:P2210

例3:P3936 (调参题)

例4:P3878

例5:P5544

posted @ 2022-08-26 21:25  infinities  阅读(36)  评论(0编辑  收藏  举报