zoukankan      html  css  js  c++  java
  • [HAOI2008]下落的圆盘

    直接暴力O(n^2)枚举 每一个圆盘和其后面落下的圆盘

    i 当前枚举的圆 j i之后的圆

    然后利用atan2函数求出(x[j]-x[i],y[j]-y[i])向量与x轴的夹角

    再根据d(圆心之间距离)、r[i]、r[j]余弦定理求出向量可以向上下扩展的角度

    用贪心线段覆盖...

    枚举的时候有几种特殊情况:

    1.两个圆相离

    2.i在j内

    3.j在i内

    4.斜率不存在的情况不用考虑,atan2函数就行了

     

     

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define dd double
    using namespace std;
    const int N=1006;
    const dd pai=acos(-1.0);
    
    struct son
    {
        dd l,r;
        bool friend operator < (son a,son b)
        {
            if(a.l==b.l)
                return a.r<b.r;
            return a.l<b.l;
        }
    }ji[N*10];
    int con;
    
    int n;
    dd r[N],x[N],y[N];
    
    inline dd dis(dd x3,dd y3,dd x4,dd y4)
    {
        return sqrt( (x4-x3)*(x4-x3)+(y4-y3)*(y4-y3) );
    }
    
    dd check()
    {
        sort(ji+1,ji+1+con);
    
        dd ans=0,las=-pai;
        for(int i=1;i<=con;++i)
        {
            if(ji[i].l<las)
            {
                if(ji[i].r>las)
                    ans+=(ji[i].r-las);
            }
            else
            {
                ans+=(ji[i].r-ji[i].l);
            }
            if(las<ji[i].r)
                las=ji[i].r;
        }
        return ans;
    }
    
    dd work()
    {
        dd ce1,ce2,d,ans=0,temp,sh,xi;
        for(int i=1;i<=n;++i)
        {
            con=0;
            for(int j=i+1;j<=n;++j)
            {
                d=dis(x[i],y[i],x[j],y[j]);
                if(d>r[i]+r[j])//i和j相离
                    continue;
                if(d+r[i]<r[j])//i整个被覆盖
                {
                    ji[++con]=(son){-pai,pai};
                    break;
                }
                if(d+r[j]<r[i])//j在i中间
                    continue;
                /*if(x[j]==x[i])
                    ce1=(y[j]-y[i]>0?pai/2.0:-pai/2.0);//直角 .... (还是别判断了...容易wa)
                else*/
                ce1=atan2( (x[j]-x[i]),(y[j]-y[i]) );
                ce2=acos( (r[i]*r[i]+d*d-r[j]*r[j])/(2*r[i]*d) );
    
                sh=ce1+ce2;xi=ce1-ce2;
                if(sh>pai)
                    ji[++con]=(son){ -pai,sh-2*pai },sh=pai;
                if(xi<-pai)
                    ji[++con]=(son){ xi+2*pai,pai },xi=-pai;
                ji[++con]=(son){ xi,sh };
    
            }
            temp=check();
            //printf("temp=%lf
    ",temp);
            ans+=((2.0*pai-temp)*r[i]);
        }
        return ans;
    }
    
    int main(){
    
        //freopen("in.in","r",stdin);
        //freopen("disc.in","r",stdin);
        //freopen("disc.out","w",stdout);
    
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
            scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
        printf("%.3lf",work());
    }
    下落的圆盘

     

  • 相关阅读:
    《构建之法》第8、9、10章的读后感和第一个sprint总结
    实验三 进程调度模拟程序
    构建之法第6、7章的读后感
    实验二 作业调度模拟程序
    0415博客园评价
    0414复利计算6.0-----结对编程
    0408~送给小伙伴的汉堡包
    学习进度条
    Sprint three
    sprint one
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7620292.html
Copyright © 2011-2022 走看看