1、问题
给定n个圆的半径序列,将它们放到矩形框中,各圆与矩形底边相切,
求具有最小排列长度的圆排列。
例如,当n=3,且所给的3个圆的半径分别为1,1,2时,这3个圆的最小长度的圆排列如图所示。其最小长度为
2、解析
所谓圆形排列应该就是圆形的每个位置是等价的,圆形排列只考虑的是排列的元素之间的关系。
圆排列问题的主要思路是排列问题,通过建立排列树,再进行回溯剪枝,得出最优排列。
每次修改一个圆的排列位置,若修改后的排列长度变小,则在当前排列的前提下继续排列,否则回溯。
每次排列后,相切情况下圆的X坐标计算公式:x2 =(r+ri)2 + (r-ri)2,推出x = 2*sqrt(r+ri);r为自身半径,ri为相切圆半径。
使用分支限界计算,一定会遍历所有的排列情况,剪枝就是当前的排列如果比之前的排列反而长,就会去除这种情况以及他的子结点,达到了减少时间的目的,要取得最佳答案。
3、设计(伪代码)
void Circle::Backtrack(int t)
{
if (t > n) //计算排列长度
Compute();
else
for (int j = t; j <= n; j++) {
swap(r[t], r[j]);//确定当前第t个圆的半径
float centerx = Center(t);
if (centerx + r[t] + r[1] < min) {
x[t] = centerx;
Backtrack(t + 1);//开始深入到第t+1个圆
}
swap(r[t], r[j]);
}
}
4、分析
最坏的情况,有n个顶点,每个顶点有m种颜色,其有n-1个子节点
O(n) = n*mn-1/m-1=O(nmn)
5、源码
https://note.youdao.com/ynoteshare1/index.html?id=162135ed88129b2280fe7126fd7c0ea6&type=notebook