zoukankan      html  css  js  c++  java
  • HDU 5531 Rebuild

    2015 ACM/ICPC 长春现场赛 E题

    三分。

    如果节点个数是奇数,那么直接列方程可以求解,因为,如果第一个圆半径变大,必然导致最后一个圆的半径变大,

    所以,节点是奇数的时候,要么无解,要么只有一组解。

    如果节点个数是偶数,如果奇数编号起点的线段长度之和不等于偶数编号起点的线段长度之和,那么必定无解,这个列方程也可以发现的。

    剩下的就要三分求最优解了,边界的确定有点小坑,第一个半径是X,第二个半径就是 L12-X,第三个半径就是L23-L12+X.....写出n个关于X的表达式,可以确定三分范围。

    至此,此题已解。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const double PI=acos(-1.0);
    const double eps=1e-6;
    
    struct Point
    {
        double x,y;
        double r;
    }P[10000+10];
    struct Line
    {
        double len;
    }L[10000+10];
    int T,n;
    double r[10000+10];
    
    bool Equal(double a,double b)
    {
        if(fabs(a-b)<eps) return 1;
        return 0;
    }
    
    double Dis(int a,int b)
    {
        return sqrt((P[a].x-P[b].x)*(P[a].x-P[b].x)+(P[a].y-P[b].y)*(P[a].y-P[b].y));
    }
    
    void read()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&P[i].x,&P[i].y);
        for(int i=1;i<=n;i++)
        {
            if(i<n) L[i].len=Dis(i,i+1);
            else L[i].len=Dis(n,1);
        }
    }
    
    void print1()
    {
        double sum=0;
        for(int i=1;i<=n;i++)
            if(P[i].r<0)
            {
                printf("IMPOSSIBLE
    ");
                return ;
            }
        for(int i=1;i<=n;i++)
            sum=sum+P[i].r*P[i].r;
        printf("%.2lf
    ",sum*PI);
        for(int i=1;i<=n;i++)
            printf("%.2lf
    ",P[i].r);
    }
    
    double ff(double R)
    {
        r[1]=R;
        for(int i=2;i<=n;i++)
            r[i]=L[i-1].len-r[i-1];
    
        double sum=0;
        for(int i=1;i<=n;i++) sum=sum+r[i]*r[i];
        return sum;
    }
    
    void solve()
    {
        if(n%2==1)
        {
            double len1=0,len2=0;
            for(int i=1;i<=n;i++)
            {
                if(i%2==0) len2=len2+L[i].len;
                else len1=len1+L[i].len;
            }
            P[1].r=(len1-len2)/2.0;
            for(int i=2;i<=n;i++)
                P[i].r=L[i-1].len-P[i-1].r;
    
            if(!Equal(L[n].len-P[1].r,P[n].r))
            {
                printf("IMPOSSIBLE
    ");
                return;
            }
            print1();
        }
    
        else if(n%2==0)
        {
            double len1=0,len2=0;
            for(int i=1;i<=n;i++)
            {
                if(i%2==1) len1=len1+L[i].len;
                else len2=len2+L[i].len;
            }
            if(len1!=len2) printf("IMPOSSIBLE
    ");
            else
            {
                double left,right,mid,midmid;
                left=0; right=min(L[1].len,L[n].len);
                double sum=0;
                for(int i=1;i<=n;i++)
                {
                    if(i%2==1)
                    {
                        sum=sum+L[i].len;
                        if(sum<right) right=sum;
                    }
                    else
                    {
                        sum=sum-L[i].len;
                        if(sum>left) left=sum;
                    }
                }
                int tot=100;
                while(tot--)
                {
                    mid=(left+right)/2.0;
                    midmid=(mid+right)/2.0;
                    double k1=ff(mid);
                    double k2=ff(midmid);
    
                    if(k1-k2>eps) left=mid;
                    else right=midmid;
    
                }
                for(int i=1;i<=n;i++)
                    if(r[i]<0)
                    {
                        printf("IMPOSSIBLE
    ");
                        return ;
                    }
                printf("%.2lf
    ",ff(midmid)*PI);
                for(int i=1;i<=n;i++) printf("%.2lf
    ",r[i]);
            }
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            read();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    C++ for(char c:s)遍历字符串||for (char c : s)和for (char& c : s)的区别
    二维数组的查找--剑指offer(C++)
    C++学习笔记之--boolalpha
    在C++中matrix.size()和matrix [0] .size()之间的区别是什么?
    C3_note
    用webpack4从零开始构建react脚手架
    php
    正则表达式基础
    DOM
    常用H5
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4934062.html
Copyright © 2011-2022 走看看