模拟退火与爬山法
通过向 chatGPT-4o-mini 提问,我注意到所有爬山法可以解决的问题模拟退火都可以解决,所以爬山法死了我不想学爬山法。
具体的,对于一个多峰函数求解最值的题目都可以用模拟退火来做。
如果现在在较优解 ,发现了一个新的解 ,如果 比 优那么 否则有一定概率接受 ,这就是模拟退火的核心思想。
考虑 没有 优秀的概率是怎么计算的:
令 ,那么我们就有 的概率更新 ,其中 是当前的温度。在进行了一次操作之后就进行降温操作,即 。
下面的内容很重要!!!!!!
我们令新算出的结果为 ,原本的答案为 。
对于求解最小值的问题,取 ,那么:
- 如果 ,那么就直接接受。
- 否则如果
exp(-del/t)>Rand()
,那么接受。
对于求解最小值的问题,一样取 ,那么:
- 如果 ,那么就直接接受。
- 否则如果
exp(del/t)>Rand()
,那么接受。
需要注意的是 exp(x)
,其中 就是自然函数,其图像如下:
发现对于 的情况 epx(x)
始终大于 ,这个概率就是没有意义的,所以 的值一定是负数才有意义。
所以上面的公式在 epx
中是取 del
还是 -del
就十分好理解了,所以这并不需要死记硬背。
形象的,放一张从 OI-Wiki 偷的图:
JSOI2004 平衡点 / 吊打XXX
练手题,但是题目太困难了,考虑给一个形式化题意:
找到一个 使 最小,输出 (可以是小数),其中 。
就是模板,按照上面的思路写就行了。
AHOI2014/JSOI2014 保龄球
考虑每一次随机交换 的位置,跑模拟退火就行了。
JSOI2016 炸弹攻击
直接随机放炸弹的位置,因为函数长得奇丑无比所以要求扰动的范围较大,生成的时候需要使用:
double xx=(rand()*2-RAND_MAX)*t+x;
而不是:
double xx=(2.0*rand()/RAND_MAX-1)*t+x;
HAOI2006 均分数据
考虑先随机分组,然后模拟退火随机改变一个元素的分组就行了。
JSOI2008 球形空间产生器
设一个变量 ,表示这个高维球体的半径,由公式 可得 ,其中 是高维球面上某一个点的坐标, 是球心的坐标。
化简得:
移项得:
其中 与球面上的点无关,因此我们可以将其看做一个系数为 的变量,右边是常量。