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\n",ans);
}
posted @ 2019-01-01 18:33  fcwww  阅读(171)  评论(0编辑  收藏  举报