• [转] 二分法求外接圆最大半径


    [转]https://blog.csdn.net/flashmsn/article/details/94642687

    题目描述:

    给出N个线段长度,试将它们头尾相接组合成一个凸多边形,使凸多边形的外接圆(多边形每个顶点都在圆上)的半径最大,求该最大半径。其中N<=10^5,线段长度均不超过100,要求算法中不涉及坐标的计算。

    思路:

    二分算法的本质就是通过不断迭代使left 和 right 在固定条件下逐渐靠近真实值,符合一定误差,所以实际上把该题放在二分扩展里面,这个所谓的最大半径的“最大”是不在求解中的,最大应该算题干,先组成一个有外接圆的凸多边形,然后求其半径即可。不要误入歧途在“最大”上绞尽脑汁。
      外接圆圆心与每个线段顶点连接后会有一个圆心角,如果圆心在凸多边形内部,则所有圆心角之和应该为2π。如果圆心在凸多边形外部,则最大的圆心角等于其他圆心角之和。
      因此设定初值,求出每个线段对应的圆心角,使所有圆心角之和等于2π。不断迭代逼近真值即可。当所求圆心角大于2π时,增大r尝试,小于2π时,缩小r尝试。
      当圆心在多边形外面时,当刚好外接圆在多边形上时,其他圆心角之和==最大圆心角。取圆心角之和为其他圆心角+2π-最大圆心角,同时逼近的方向与前面相反。
      半径应该大于等于最大边的一半。其中等于的情况单独处理。

      #include<cstdio>
     #include<cmath>
     const double PI=acos(-1.0);
     const double eps=1e-5;//比较精度
      //求圆心角之和
    double totalCornerAngles(double edges[],int n,double r)
    {
        double sum = 0.0;
        for(int i =0;i<n;i++)
            sum+=asin(edges[i]/2/r)*2;
        return sum;
    }
    //二分法求半径
    
    int main()
    {
    
        int N;//边数
        scanf("%d",&N);//输入边数
        double edges[N];//边长数组
    
        double sum;//圆心角之和
        double maxAngle=0.0;//最长边对应的圆心角
        double maxEdge=0.0;//最长边
    
    
        //初始化edges
        for(int i=0;i<N;i++)
        {
            scanf("%lf",&edges[i]);
            if(edges[i]>maxEdge)
                maxEdge = edges[i];//保存最大边
        }
        //以最长边为直径求圆心角之和,若为2π则直接返回
        sum = totalCornerAngles(edges,N,maxEdge/2);
        if(fabs(sum-PI*2)<eps)
        {
            printf("外接圆的最大半径是最大边的一半:%.2f",maxEdge/2);
            return 0 ;
        }
    
        //半径大于最大边的一半(即斜边大于直角边)
        double left =maxEdge/2,right=10000000,mid;
        double other=0;
    
         //在误差范围内循环求解
        while(right -left >eps)
        {
             mid = (right + left) /2;
             maxAngle=asin(maxEdge/2/mid)*2;//求出最大边对应的圆心角
             sum = totalCornerAngles(edges,N,mid);
             other=sum-maxAngle;
             //如果除去最大圆心角的其他圆心角之和小于π,说明圆心在多边形外面
             if(other<PI)
             {
                 sum=other+2*PI-maxAngle;
                 if( sum<2*PI)
                     left = mid;
                 else
                     right = mid;
             }
             //圆心在多边形里面
             else
             {
                 if( sum>2*PI)
                     left = mid;
                 else
                    right = mid;
             }
        }
        printf("外接圆的最大半径是:%.2f",mid);
        return 0;
     }
    
    
    
  • 相关阅读:
    https://www.unavco.org/projects/projectsupport/boreholeservices/bsmliterature/bsmliterature.html
    SpringBoot+log4j2+MDC+AOP记录requestId
    CVE_2020_0796 SMBGhost浅析
    CVE20201301 SMBLost漏洞浅析
    Alpine容器安装运行ssh
    cut用法详细解析
    #、##、__VA_ARGS__的使用
    电子地图监控
    mybatisgeneratorgui selectkey
    Native.loadLibrary
  • 原文地址:https://www.cnblogs.com/Hsiung123/p/13812065.html
Copyright © 2020-2023  润新知