算法分析大作业 圆排列问题

算法分析与设计

圆排列问题

问题描述:

给定n个圆的半径序列,将它们放到矩形框中,各圆与矩形底边相切,求具有最小排列长度的圆排列。

算法

假设三个圆的半径分别为1,1,2。那么这种情况的圆排列长度为2+4sqrt(2)。计算r1=1,r2=2情况下的两圆心的距离为len2=(r1+r2)2-(r2-r1)^2。推广到所有情况就可以得到len=2sqrt(r1*r2)。
在这里插入图片描述
在这里插入图片描述
这是n=3时,圆A,圆B,圆C的排列数的情况。ABC,ACB,BCA,BAC,CAB,CBA。圆排列问题的解空间是一颗排列树。按照回溯法搜索排列树的算法框架,设开始时r=[r1,r2,…,rn]是所给的n个圆的半径,则相应的排列树由r[1:n]的所有排列构成。
compute函数:可以想象其中任意的一个圆无限大或无限小,无限大的话那其余的圆就可以统统忽略了。已知所有圆的x[]和r[],求出每个圆的左右坐标,通过比较找出最小的左部坐标和最大的右部坐标,想减就是该圆排列的长度,每次更新出最小的minn。

核心代码:

double Getc(int t) {         //计算第t个圆的圆心坐标
    double temp = 0;
    for (int j = 1; j < t; ++j) {
        double val = x[j] + 2.0 * sqrt(r[t] * r[j]);  //判断与他之前的所有圆相切的情况
        temp=max(temp,val);
    }
    return temp;
}
void compute() {
    double L = inf, R = 0;   //L是左边界,R是有边界
    for (int i = 1; i <= n; ++i) {
        if (x[i] - r[i] < L)
            L = x[i] - r[i];
        if (x[i] + r[i] > R)
            R = x[i] + r[i];
    }
    if (R - L < minn) {
        minn = R - L;
        for (int i = 1; i <= n; ++i)
            arr[i] = r[i];
    }
}
void dfs(int t) {
    if (t == n + 1) {
        compute();
    }
    else {
        for (int j = t; j <= n; ++j) {
            swap(r[t], r[j]);
            double val = Getc(t);
            if (val + r[t] + r[1] < minn) {
                x[t] = val;
                dfs(t + 1);
            }
            swap(r[t], r[j]);     //还原
        }
    }
}



时间复杂度:

算法遍历解空间,时间复杂度为O(n!)。
每次计算圆排列长度,此时的时间复杂度为O(n)。
综上,该算法的时间复杂度为O(n!*n)。

源码:

https://github.com/SpiritDemon-max/myText/blob/master/circle.cpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值