1. 问题
圆排列问题:给定n个圆的半径序列,将它们放到矩形框中,各圆与矩形底边相切,求具有最小排列长度的圆排列。
2. 解析
首先举一个例子,当给定的圆半径为1,1,3时则可以给出如下排列使排列长度最小:
所以这题也算是一个排列问题,如何排列能够使排列的长度最小。
在排列时有以下几种情况:
1、每个圆相继相切:
如上面的例子里每个圆都和旁边的圆相切
2、其中一个圆很小,两边的圆很大:
3、有一个圆很大其他很小:
所以排在任意位置的圆与其前或后的任意一个圆都有可能相切的
- center计算圆在当前圆排列中的横坐标,由x^2 = sqrt((r1+r2)2-(r1-r2)2)推导出x = 2sqrt(r1r2)。由于第t个圆很可能跟前面任何一个圆相切。这时,只要把各种情况得到取值全部算出,并把最大值记录下来,所以在for循环里。
- Compute计算当前圆排列的长度。变量lenmin记录当前最小圆排列长度。数组r存储所有圆的半径。数组x则记录当前圆排列中各圆的圆心横坐标。
- 在递归算法Backtrack中,当i>n时,算法搜索至叶节点,得到新的圆排列方案。此时算法调用Compute计算当前圆排列的长度,适时更新当前最优值。当i<n时,当前扩展节点位于排列树的i-1层。此时算法选择下一个要排列的圆,并计算相应的下界函数。
3. 设计
伪代码为:
double center(int t){
//计算圆心坐标
for(