核心思路就是模拟物理上的退火过程,有一个初温和末温,和降温系数(每次初温乘以系数),当初温大于末温时,我们随机一个解,并尝试更新当前解,当不大于末温时退火结束。
更新的方法:
如果新解严格优于当前解,直接更新。如果劣于,以一定的概率接受新解,一定的概率不接受,且新解越劣、当前温度越低更新新解的概率越低。
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
标签:系数,劣于,退火,更新,新解,模拟退火 From: https://www.cnblogs.com/infinities/p/16629330.html