【HAOI2008】bzoj1043 下落的圆盘

来源:互联网 发布:linux安装zip解压软件 编辑:程序博客网 时间:2024/04/24 05:07

Description

  有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红 色线条的总长度即为所求. Input

  第一行为1个整数n,N<=1000 接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.

Output

  最后的周长,保留三位小数

可以算是【uva1308 Viva Confetti】的升级版。
这回不能O(n3)枚举判断每一段小圆弧是否被覆盖了,可以把一个圆和在他上面的圆交出的所有圆弧找出来,找到这些弧的并集的补集就是这个圆露出的部分。求并集的时候可以转化为序列上的问题,做法就很多了。

#include<cstdio>#include<cmath>#include<vector>#include<algorithm>using namespace std;const double eps=1e-8,pi=acos(-1);int dcmp(double x){    if (x>eps) return 1;    if (fabs(x)<eps) return 0;    return -1;}struct Vector{    double x,y;    void rd()    {        scanf("%lf%lf",&x,&y);    }    Vector operator + (const Vector &v) const    {        return (Vector){x+v.x,y+v.y};    }    Vector operator - (const Vector &v) const    {        return (Vector){x-v.x,y-v.y};    }    Vector operator * (const int &k) const    {        return (Vector){x*k,y*k};    }    Vector operator / (const int &k) const    {        return (Vector){x/k,y/k};    }};typedef Vector Point;double dot(Vector v,Vector u){    return v.x*u.x+v.y*u.y;}double cross(Vector v,Vector u){    return v.x*u.y-v.y*u.x;}double length(Vector v){    return sqrt(dot(v,v));}double dis(Point p,Point q){    return length(p-q);}double convert(double a){    while (dcmp(a)==-1) a+=2*pi;    while (dcmp(a-2*pi)>=0) a-=2*pi;    return a;}struct Circle{    Point o;    double r;    void rd()    {        scanf("%lf",&r);        o.rd();    }}a[1010];bool in(Circle c1,Circle c2){    return dcmp(dis(c1.o,c2.o)-(c2.r-c1.r))<=0;}vector<pair<double,int> > ang;vector<pair<double,int> >::iterator it;void getintersection(Circle c1,Circle c2){    double d=dis(c1.o,c2.o);    if (dcmp(d-(c1.r+c2.r))>=0||dcmp(d-(c1.r-c2.r))<=0) return;    double a1=atan2(c2.o.y-c1.o.y,c2.o.x-c1.o.x),a2=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));    double s=convert(a1-a2),t=convert(a1+a2);    if (dcmp(s-t)==1)    {        ang.push_back(make_pair(0,1));        ang.push_back(make_pair(t,-1));        ang.push_back(make_pair(s,1));        ang.push_back(make_pair(2*pi,-1));    }    else    {        ang.push_back(make_pair(s,1));        ang.push_back(make_pair(t,-1));    }}double count(){    double ret=0;    int cnt=0;    sort(ang.begin(),ang.end());    if (ang.empty()) return 0;    for (it=ang.begin();(it+1)!=ang.end();it++)    {        cnt+=(*it).second;        if (cnt) ret+=(*(it+1)).first-(*it).first;    }    return ret;}void check(){    for (it=ang.begin();it!=ang.end();it++)        printf("%.3f %.3f\n",(*it).first,(*it).second);}int n;int main(){    /*freopen("disc.in","r",stdin);    freopen("disc.out","w",stdout);*/    int ok;    double ans=0;    scanf("%d",&n);    for (int i=1;i<=n;i++) a[i].rd();    for (int i=1;i<=n;i++)    {        ang.clear();        ok=1;        for (int j=i+1;j<=n&&ok;j++)        {            if (in(a[i],a[j])) ok=0;            else getintersection(a[i],a[j]);        }        if (ok) ans+=a[i].r*(2*pi-count());        /*if (i==4) check();        if (dcmp(ans)==-1)        {            printf("%d\n",i);            break;        }*/    }    printf("%.3f\n",ans);}
1 0
原创粉丝点击