• 《算法笔记》二分—木棒切割问题&求凸多边形外接圆最大半径


    木棒切割问题

    大意:给N根木棒,通过切割至少得到K段长度相同的木棒,长度相同的木棒最长能有多长
    思路:已知结论,长度相同的木棒长度越长,切割得到的K越小,可以二分法,即求最后一个满足“k<=K”的L,可转换为第一个满足“k>K”的位置,再减一

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    int main()
    {
        int n,K,k=0,length[10];
        scanf("%d%d",&n,&K);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&length[i]);
        }
        sort(length,length+n);
        int left=1,right=length[n-1],mid;
        while(left<right)
        {
            k=0;
            mid=(left+right)/2;
            for(int i=0;i<n;i++)
            {
                k+=length[i]/mid;
            }
            if(k<K) right=mid;
            else left=mid+1;
        }
        printf("%d",mid-1);
        return 0;
    }
    

    二分法求凸多边形外接圆最大半径

    大意:给定N条线段,按任意顺序首尾相连,组合成一个凸多边形,使得其外接圆半径最大,求最大半径
    思路:首先判断外接圆圆心在多边形内或外或在多边形上。
    1.多边形的外接圆的圆心在多边形上或内,所有线段对应的圆心角sum_angle之和为2pi。
    将外接圆半径和圆心角之和的关系进行二分
    sum_angle<2pi,说明当前半径r需要减小
    sum_angle>2pi,说明当前半径r需要增大
    2.多边形的外接圆院系在多边形之外,最长线段所对应的圆心角一定为其他角之和
    判断条件:其他角之和(other_angle)+2pi-最大角(max_angle)
    如果小于2pi,说明半径r需要增大
    如果大于2pi,说明半径r需要减小
    二分边界:left=最大边长2(斜边大于直角边),right=10000000

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn =10010;
    const double pi=acos(-1.0);
    const double eps=1e-5;
    
    double sum_angle(int length[],int n,double R)
    {
        double ans=0;
        for(int i=0;i<n;i++)
        {
            ans+=2*asin(length[i]/2/R);
        }
        return ans;
    }
    
    double radis(int length[],int n)
    {
        double sum,max_angle,other_angle;
        double left,right,mid;
        left=1.0*length[n-1]/2;
        right=1000000;
        sum=sum_angle(length,n,1.0*length[n-1]/2);
        if(fabs(sum-pi*2)<eps)//圆心在最长边上
            return length[n-1]/2;
        while(right-left>eps)
        {
            mid=(left+right)/2;
            if(other_angle<pi)//圆心在外部
            {
                other_angle=sum_angle(length,n-1,mid);
                if(fabs(other_angle+2*pi-max_angle)<eps)
                    return mid;
                else if(other_angle+2*pi-max_angle<2*pi)
                    left=mid;
                else right=mid;
            }
            else//圆心在内部
            {
                sum=sum_angle(length,n,mid);
                if(fabs(sum-2*pi)<eps)
                    return mid;
                else if(sum>2*pi)
                    left=mid;
                else
                    right=mid;
            }
        }
        return mid;
    }
    
    int main()
    {
        int n,length[maxn];//边数
        double r;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&length[i]);
        }
        sort(length,length+n);//将边数排序
        r=radis(length,n);
        printf("%.2f
    ",r);
        return 0;
    }
    
    

    有错误请之处

    作者:inss!w!
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 相关阅读:
    Asp.net导出Excel文件
    Ext.Net 使用总结之GridPanel中的选中行
    Ext.Net 使用总结之查询条件中的起始日期
    使用python crontab设置linux定时任务
    JSON Serialization/Deserialization in C#
    redis 基本数据类型-列表(List)
    redis 基本数据类型-字符串(String)
    使同一个server上不同port的django应用可在同一个浏览器上打开
    django server之间通过remote user 相互调用
    使用python实现短信PDU编码
  • 原文地址:https://www.cnblogs.com/Hfolsvh/p/14371398.html
Copyright © 2020-2023  润新知