圆排列C++

Description

给定n个大小不等的圆c1,c2,…,cn,现要将这n个圆排进一个矩形框中,且要求各圆与矩形框的底边相切。圆排列问题要求从n个圆的所有排列中找出有最小长度的圆排列。例如,当n=3,且所给的3个圆的半径分别为1,1,2时,这3个圆的最小长度的圆排列如下图所示。(注意,只要求圆和矩形框底边相切,不要求相邻圆都相切)

图片1.png

Input

输入为两行,第一行为一个整数n,即圆的个数;第二行为n个数,即圆的

Output

输出为一个浮点数,取到小数点后2位,即圆排列的最小长度

Sample Input 1 

3
1 1 2

Sample Output 1

7.65

思路

他只给出半径,没给顺序,所以给他来个全排列。

假设大的圆的半径x,小的圆的半径y

根据勾股定理,那么矩形底边的那段长就是(x+y)*(x+y)-(x-y)*(x*-y)然后开根号

把所有这样的结果(1到2,2到3····一直到n-1到n)全部加起来,再加上第一个和最后一个圆的半径,就是底边的长了。

然后取最小的。

代码

#include<bits/stdc++.h>
using namespace std;
int n;
int r[1000];//存放半径

double calculate(int r[],int n,double minL){
    double x,y;//表示两个圆的半径
    double sum=0;
    for(int i=1;i<n;i++){
        //取大的半径为x,小的为y
        if(r[i]>r[i+1]){
            x=r[i];
            y=r[i+1];
        }else{
            y=r[i];
            x=r[i+1];
        }
        //两个圆的矩形边方向的距离
        sum+= sqrt((x+y)*(x+y)-(x-y)*(x-y));
        if(sum>minL)//可以剪枝优化一下,如果当前sum已经大于minL直接结束当前循环
			break;
    }
    sum+=r[1]+r[n];//加上开头和结束
    minL=min(minL,sum);
    return minL;
}

int main(){
    cin>>n;
    double ans=DBL_MAX;//取一个无穷大
    for(int i=1;i<=n;i++){
        cin>>r[i];
    }
    do{
        ans=calculate(r,n,ans);
    }while(next_permutation(r+1,r+n+1));//全排列
    printf("%.2f",ans-0.005);//减去0.005来进行浮点数精度修正
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值