This program is used to solve a algorithm problem.
The detailed description is that in a given box by [-1,1], given m balloons(they cannot overlap) with variable radio r and position mu, some tiny blocks are in the box at given posiion {d}, which balloons cannot overlap with, we should find the optimal value of r nd mu which maxmizes sum r^2.
题目翻译:给定一个矩形区域,x 的范围为 (-1, 1), y 的范围为 (-1, 1),同时在这个矩形区域中有 m 个 blocker点,现需要求得 n 个圆,使这 n 个圆的面积和最大,n 个圆满足如下约束:
- 圆必须在矩形区域内
- 圆内不得包含任意一个 blocker点, 可以在圆上
- n 个圆之间不能互相相交, 可以相切
本题选取算法:算法三
时间复杂度:O(percision) # percision 精度
-
将给出的矩形区域按照精度(percision) 划分为均匀区域,记 dots 为这些区域的交点
-
遍历 dots 取出最大圆
最大的圆的获取方法:dot 到边界,到blockers 的距离中最小的一个即为最大的圆的半径
-
循环 n 次
缺点:不言而喻
思想:每次从当前解的临近解空间中选择一个最优解作为当前解,直到达到一个局部最优解。
缺点:可能陷入局部最优解,不一定能搜索到全局最优解
如图1所示:假设C点为当前解,爬山算法搜索到A点这个局部最优解就会停止搜索,因为在A点无论向那个方向小幅度移动都不能得到更优的解。
思想:模拟退火算法以爬山算法为基础,但是以一定的概率来接受一个比当前解要差的解,因此有可能会跳出这个局部的最优解,从而达到全局的最优解。
如上图示例,模拟退火算法在搜索到局部最优解A后,会以一定的概率接受到E的移动。也许经过几次这样的不是局部最优的移动后可能会到达D点,于是就跳出了局部最大值A。
模拟退火算法描述:
若移动后得到更优解,则总是接受该移动
若移动后的解比当前解要差,则以一定的概率接受移动,而且这个概率随着时间推移逐渐降低(逐渐降低才能趋向稳定)
这里的“一定的概率”的计算参考了金属冶炼的退火过程,这也是模拟退火算法名称的由来。
根据热力学的原理,在温度为T时,出现能量差为dE的降温的概率为P(dE),表示为:
P(dE) = exp( dE/(kT) )
其中k是一个常数,exp表示自然指数,且dE<0。这条公式说白了就是:温度越高,出现一次能量差为dE的降温的概率就越大;温度越低,则出现降温的概率就越小。又由于dE总是小于0(否则就不叫退火了),因此dE/kT < 0 ,所以P(dE)的函数取值范围是(0,1) 。
随着温度T的降低,P(dE)会逐渐降低。
我们将一次向较差解的移动看做一次温度跳变过程,我们以概率P(dE)来接受这样的移动。
本题中只需要首先随机选取一个出发点,之后在一定范围(设定预定参数)内进行模拟退火算法即可获取最大圆
缺点:不如暴力求解精度高
优点:由于引入随机因子,时间复杂度大大减少
时间复杂度:O(1)
- 三点确定一个圆
- 两点一条切线确定一个圆
- 一点两条切线确定一个圆
- 三条切线确定一个圆
综合:
其实以上四种情况可以归结为一种情况:
若要确定圆A,只需给出与A相切的三个圆B, C, D即可
公式如下:
( x - x1)^2^ + ( y - y1)^2^ = ( r + r1)^2^
( x - x2)^2^ + ( y - y2)^2^ = ( r + r2)^2^
( x - x3)^2^ + ( y - y3)^2^ = ( r + r3)^2^
三个方程三个未知数即可求解出 唯一的 (x, y, r)
注:一个点可看做一个半径为 0 的圆,一条切线可看做半径无穷大的圆
题目中给出了一个矩形区域,以及 m 个 blocker点
于是初始条件如下:
-
四个半径无穷大的圆
# config.py # BORDER 假定为无穷大 BORDER = 1e20 # 格式:(x, y, r) CONDITIONS = [ (-BORDER, 0.0, BORDER), (BORDER, 0.0, BORDER), (0.0, -BORDER, BORDER), (0.0, BORDER, BORDER), ]
-
m 个半径为 0 的圆
CONDITIONS = [ (blocker[0], blocker[1], 0) for blocker in blockers ]
- n 次循环 (n 为要求求出的圆的个数)
- 在给出的条件中每次抽取 三个,一共有 C
m+4^3^ = (m+4) * (m+3) * (m+2) 种组合 - 利用三个条件圆确定一个圆
- 每次比较,保存最大的圆
- 一次循环之后 确定的圆也就成为条件之一,故需要将确定的圆也加入到条件中
- 如此循环 n 次即可
注:对于半径为无穷大的圆在方程中需要特殊处理
