说在前面
早在本蒟蒻还没有退役的时候,yuzan1830就已经酝酿好了题目。鉴于本蒟蒻的水瓶水平,当时题目没有解决。于是非常无情地,这道题被咕掉了。
题目原型是这样的:平面内有一些圆,每个圆有一定的半径。圆的位置可以移动,但不能有重叠。现在需要在平面内找到一个矩形,使得这些圆都在矩形内,且矩形的面积最小。求最小面积。yuzan1830并不喜欢特别多的输入,于是他只给出了半径为某个值的圆的数量,而不是给出每个圆的半径。
这里不讨论过去一年的时间里yuzan1830是如何破茧成蝶、寻找成长的价值,以及本蒟蒻是如何放弃挑战、走向自闭的深渊, 现在直接进入正题:模拟退火。
重拾挑战
模拟退火的核心是以一定概率接受随机产生的新解。以求函数 的最小值为例,这个概率为( 为当前的温度):
除此之外就是如何产生新解以及调参的问题。
本题最大的问题是圆的位置不确定。不过用上模拟退火就显得简单粗暴了,将矩形的面积看成是关于圆的位置集合的一个函数 , ,随机确定每个圆的位置,然后可以通过求此时矩形的最小面积作为函数值,再用模拟退火求函数 的最小值。
在圆的位置确定的情况下求矩形的最小面积成了另一个问题。显然矩形的每条边一定和至少一个圆相切。如果知道了矩形两条邻边的倾斜角 ,就可以用两条倾斜角分别为 的直线去和每一个圆相切,得到两组平行线,最外边的四条直线围成的图形即为所求矩形。而 中一定有一个角在 范围内(设为 ),而另一个角就是 。此时矩形的面积又可以看成是关于 的函数 。
然后又用模拟退火求 的最小值?没有必要。如果另行作一个函数 表示 时矩形的面积1,虽然 时矩形的面积不一定最小,但对问题的最终答案没有影响。考虑把圆的位置集合为 时面积最小的矩形及所有的圆绕原点旋转,保持相对位置不变,旋转到矩形的四条边与坐标轴平行为止。记旋转后圆的位置集合为 ,矩形的倾斜角为 。于是 ,那么有
而圆的位置是随机的, 函数能取到的值, 函数都能取到。因此只需要求 的最小值作为最终答案,连切线都不需要算了,直接取所有圆的上下左右边界。
初始解设置为所有的圆排成一列。生成新解的时候,随机选择一个圆,随机移动到附近的一个位置,移动的距离随温度下降而减少。如果移动后的圆与其它的圆出现了重叠,简单粗暴地重新生成新解。
这里的 不表示 的导数。 ↩︎