• BZOJ1043: [HAOI2008]下落的圆盘


    BZOJ1043: [HAOI2008]下落的圆盘

    https://lydsy.com/JudgeOnline/problem.php?id=1043

    分析:

    • 这题我写了(2k)..
    • 先是(O(n^2))枚举覆盖的圆盘,求出被覆盖的弧度范围([l,r])
    • 这个我们用余弦定理求一下即可。
    • 注意(atan2(x,y))求的是((x,y))的夹角。
    • 求出来之后排序+扫描线求哪些是被覆盖过的。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <cmath>
    using namespace std;
    typedef double f2;
    #define N 1050
    #define eps 1e-8
    const f2 pi = acos(-1);
    f2 pf(f2 x) {return x*x;}
    struct Point {
        f2 x,y;
        Point() {}
        Point(f2 x_,f2 y_) {x=x_,y=y_;}
        Point operator + (const Point &p) const {return Point(x+p.x,y+p.y);}
        Point operator - (const Point &p) const {return Point(x-p.x,y-p.y);}
        Point operator * (f2 rate) const {return Point(x*rate,y*rate);}
    };
    f2 cross(const Point &p1,const Point &p2) {return p1.x*p2.y-p1.y*p2.x;}
    f2 dis(const Point &p1,const Point &p2) {return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}
    struct Circle {
        Point p; f2 r;
    }a[N];
    struct A {
        f2 x,v;
        bool operator < (const A &u) const {return x<u.x;}
    }pos[N<<1];
    int n; f2 ans;
    int main() {
        scanf("%d",&n);
        int i,j;
        for(i=1;i<=n;i++) {
            scanf("%lf%lf%lf",&a[i].r,&a[i].p.x,&a[i].p.y);
        }
        for(i=1;i<=n;i++) {
            int m=0,now=0;
            for(j=i+1;j<=n;j++) {
                f2 x=a[i].r,y=a[j].r,z=dis(a[i].p,a[j].p);
                if(x+z<=y) {
                	now=m=0; ans-=2*pi*a[i].r; break;
                }
                if(x+y<z||x+z<y||y+z<x) continue;
                f2 cy=acos((pf(x)+pf(z)-pf(y))/(2*x*z));
                f2 ct=atan2(a[j].p.x-a[i].p.x,a[j].p.y-a[i].p.y);
                f2 l=0.5*pi-ct-cy,r=l+2*cy;
                while(l<0) l+=2*pi;
                while(l>2*pi) l-=2*pi;
                while(r<0) r+=2*pi;
                while(r>2*pi) r-=2*pi;
                pos[++m]=(A){l,1};
                pos[++m]=(A){r,-1};
                if(l>r) now++;
            }
            pos[++m]=(A){2*pi,0};
            sort(pos+1,pos+m+1);
            ans+=2*pi*a[i].r;
            for(j=1;j<=m;j++) {
                if(now>0) {
                    ans-=(pos[j].x-pos[j-1].x)*a[i].r;
                }
                now+=pos[j].v;
            }
        }
        printf("%.3f
    ",ans);
    }
    
  • 相关阅读:
    继承人人前端笔试题
    【转】ASP.NET应用程序生命周期趣谈
    C#中正则表达式的高级应用
    使用C#导入导出数据到Excel
    Server.Transfer详细解释
    防止刷新重复post提交
    程序只运行一次的方法
    注释很全的抽象工厂(没用简单工厂优化)
    利用反射动态调用类成员C#
    编程经历的一些思考
  • 原文地址:https://www.cnblogs.com/suika/p/10205484.html
Copyright © 2020-2023  润新知