BZOJ 1043 [HAOI2008]下落的圆盘 ——计算几何

倒着考虑,加入一个圆,判断和前面有没有完全覆盖的情况。

如果没有,和圆盘一一取交集,然后计算它们的并集,然后计算即可。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define eps 1e-8
#define sqr(x) x*x
#define ll long long
#define mp make_pair
 
const double pi=acos(-1.0);
 
struct Vector{
    double x,y;
    void print()
    {
        printf("Vector -> (%.3f,%.3f)\n",x,y);
    }
};
 
struct Point{
    double x,y;
    void print()
    {
        printf("Point . (%.3f,%.3f)\n",x,y);
    }
};
 
Vector operator + (Vector a,Vector b)
{Vector ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;}
 
Vector operator - (Vector a,Vector b)
{Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
 
Point operator + (Point a,Vector b)
{Point ret;ret.x=a.x+b.x;ret.y=a.y+b.y;return ret;}
 
Vector operator - (Point a,Point b)
{Vector ret;ret.x=a.x-b.x;ret.y=a.y-b.y;return ret;}
 
Vector operator * (Vector a,double b)
{Vector ret;ret.x=a.x*b;ret.y=a.y*b;return ret;}
 
double operator * (Vector a,Vector b)
{return a.x*b.y-a.y*b.x;}
 
Vector Turn(Vector a,double b)
{
    Vector ret;
    ret.x=a.x*cos(b)-a.y*sin(b);
    ret.y=a.x*sin(b)+a.y*cos(b);
    return ret;
}
 
void debug()
{
    Vector v1,v2,v3; Point p1,p2,p3;
    v1.x=3;v1.y=0;v2.x=0;v2.y=2;
    printf("Test one\n");
    v1.print(); v2.print(); printf("The Area is %.3f\n\n",v1*v2);
    printf("Tet Two\n");
    v1.print(); v1=Turn(v1,pi/4);
    printf("Turn in π/4\n");
    v1.print(); printf("\n");
    v1=Turn(v1,-pi/4);
    printf("Turn in -π/4\n");
    v1.print(); printf("\n");
}
 
int n;
 
struct Circle{
    double x,y,r;
    void print()
    {
        printf("Circle (%.3f,%.3f) r = %.3f\n",x,y,r);
    }
}a[1005];
 
double dst(double x1,double y1,double x2,double y2)
{return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
 
int dcmp(double x)
{
    if (x>eps) return 1;
    if (fabs(x)<eps) return 0;
    return -1;
}
 
bool in(Circle a,Circle b)
{
    if (dcmp(dst(a.x,a.y,b.x,b.y)-(b.r-a.r))<=0) return true;
    return false;
}
 
struct Cut_Cir{
    double l,r;
    void print()
    {
        printf("Ang (%.3f,%.3f)\n",l,r);
    }
}sta[1000005];
int top=0;
 
double nege(double x)
{
    if (dcmp(x)==-1) x+=2*pi;
    while (dcmp(x-2*pi)>=0) x-=2*pi;
    return x;
}
 
void Cut(int pos)
{
    top=0; double dist; Vector v0,v1,v2;
    F(i,pos+1,n)
        if ((dist=dst(a[pos].x,a[pos].y,a[i].x,a[i].y))<a[pos].r+a[i].r)
        {
            double ang; ang=(sqr(a[pos].r)+sqr(dist)-sqr(a[i].r))/(2*a[pos].r*dist);
            if (ang>1.0) continue;
            ang=acos(ang);
            v0.x=a[i].x-a[pos].x;v0.y=a[i].y-a[pos].y;
            v0=v0*(1.0/sqrt(sqr(v0.x)+sqr(v0.y))*a[pos].r);
            v1=Turn(v0,ang);
            v2=Turn(v0,-ang);
            double t1=atan2(v1.y,v1.x),t2=atan2(v2.y,v2.x);
            t1+=pi;t2+=pi;
            while (t1>2*pi) t1-=2*pi;
            while (t2>2*pi) t2-=2*pi;
            if (t1<t2)
            {
                ++top;
                sta[top].l=0;
                sta[top].r=t1;
                ++top;
                sta[top].l=t2;
                sta[top].r=2*pi;
            }
            else
            {
                ++top;
                sta[top].l=t2;
                sta[top].r=t1;
            }
        }
}
 
double C(Circle a)
{return a.r*2*pi;}
 
bool cmp2(Cut_Cir a,Cut_Cir b)
{return a.l<b.l;}
 
double cal(double r)
{
    sort(sta+1,sta+top+1,cmp2);
    double now=0,ret=0;
    F(i,1,top)
    {
        now=max(now,sta[i].l);
        ret+=max(0.0,sta[i].r-now);
        now=max(now,sta[i].r);
    }
    return ret*r;
}
 
double ans=0;
 
int main()
{
    scanf("%d",&n);
    F(i,1,n) scanf("%lf%lf%lf",&a[i].r,&a[i].x,&a[i].y);
    F(i,1,n)
    {
        int flag=1;
        F(j,i+1,n) if (in(a[i],a[j]))
        {
            flag=0;
        }
        if (!flag) continue;
        Cut(i);
        ans+=C(a[i]);
        ans-=cal(a[i].r);
    }
    printf("%.3f\n",ans);
}

  

posted @ 2017-04-09 19:54  SfailSth  阅读(150)  评论(0编辑  收藏  举报