zoukankan      html  css  js  c++  java
  • bzoj 2178

    这题调精度真痛苦啊(向管理员要了数据才调出来)。

    用的是hwd在WC2015上讲的方法,考虑将原图分割,根据每个圆的左右边界和圆与圆交点的横坐标来分割,这样原图就被分成很多竖着的长条,并且每一条中间都没有交点,这样就有一个性质:每一条都是"弓形-梯形-弓形 弓形-梯形-弓形..."的形式,然后从一个方向开始,记录当前进入的圆的数量,每当出来就就计算面积。

      1 /**************************************************************
      2     Problem: 2178
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:1248 ms
      7     Memory:48560 kb
      8 ****************************************************************/
      9 
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <cmath>
     13 #include <algorithm>
     14 #define eps 1e-11
     15 #define N 2010
     16 using namespace std;
     17 
     18 
     19 inline int sg( long double x ) { return (x>-eps)-(x<eps); }
     20 struct Vector {
     21     long double x, y;
     22     Vector(){}
     23     Vector( long double x, long double y ):x(x),y(y){}
     24     Vector operator+( const Vector & b ) const { return Vector(x+b.x,y+b.y); }
     25     Vector operator-( const Vector & b ) const { return Vector(x-b.x,y-b.y); }
     26     Vector operator*( long double b ) const { return Vector(x*b,y*b); }
     27     Vector operator/( long double b ) const { return Vector(x/b,y/b); }
     28     long double operator^( const Vector & b ) const { return x*b.y-y*b.x; }
     29     long double operator&( const Vector & b ) const { return x*b.x+y*b.y; }
     30     long double ang() { return atan2(y,x); }
     31     long double len() { return sqrt(x*x+y*y); }
     32     long double len2() { return x*x+y*y; }
     33 };
     34 typedef Vector Point;
     35 struct Circle {
     36     Point c;
     37     long double r;
     38     Circle(){}
     39     Circle( Point c, long double r ):c(c),r(r){}
     40     inline bool in( Point &p ) {
     41         Vector vv=p-c;
     42         return (vv.x*vv.x+vv.y*vv.y) < r*r*0.999;
     43     }
     44     Point pt( long double ang ) const {
     45         return c+Vector(cos(ang),sin(ang))*r;
     46     }
     47 };
     48 struct Arc {
     49     int cid, type;
     50     long double al, ar;
     51     Point pa, pb;
     52     Arc(){}
     53     Arc( int cid, int type, const Point &a, const Point &b );
     54     long double area();
     55 };
     56 
     57 int n;
     58 bool del[N], has[N];
     59 long double spt[N*N]; int stot;
     60 Circle cir[N];
     61 Arc arc[N+N];
     62 
     63 bool cmp_arc( const Arc &a, const Arc &b ) {
     64     if( sg(a.pa.y-b.pa.y)!=0 ) return sg(a.pa.y-b.pa.y)<0;
     65     if( sg(a.pb.y-b.pb.y)!=0 ) return sg(a.pb.y-b.pb.y)<0;
     66     if( a.type!=b.type ) return a.type>b.type;
     67     if( a.type==1 ) {
     68         return cir[a.cid].r < cir[b.cid].r;
     69     } else {
     70         return cir[a.cid].r > cir[b.cid].r;
     71     }
     72 }
     73 bool cmp_cir_r( const Circle &a, const Circle &b ) { return a.r<b.r; }
     74 Arc::Arc( int cid, int type, const Point &a, const Point &b ) {
     75     this->cid = cid;
     76     this->type = type;
     77     pa = a;
     78     pb = b;
     79     this->al = (a-cir[cid].c).ang();
     80     this->ar = (b-cir[cid].c).ang();
     81     if( pa.x>pb.x ) swap(pa,pb);
     82 }
     83 long double Arc::area() {
     84     long double da = ar-al;
     85     while( sg(da)<=0 ) da+=M_PI+M_PI;
     86     while( sg(da-M_PI-M_PI)>0 ) da-=M_PI+M_PI;
     87     return (da-sin(da))*cir[cid].r*cir[cid].r/2.0;
     88 }
     89 int ccinter( int ca, int cb, Point *p ) {
     90     if( cir[ca].r<cir[cb].r ) swap(ca,cb);
     91     long double cd = (cir[ca].c - cir[cb].c).len2();
     92     long double s1 = cir[ca].r-cir[cb].r;
     93     long double s2 = cir[ca].r+cir[cb].r;
     94     s1=s1*s1, s2=s2*s2;
     95 
     96     if( sg(cd-s1)<0 || sg(cd-s2)>0 ) return 0;
     97     if( sg(cd-s1)==0 || sg(cd-s2)==0 ) {
     98         long double ang = (cir[cb].c-cir[ca].c).ang();
     99         p[0] = cir[ca].pt(ang);
    100         return 1;
    101     } 
    102     long double r1 = cir[ca].r, r2 = cir[cb].r;
    103     long double base = (cir[cb].c-cir[ca].c).ang();
    104     long double delta = acos( (r1*r1+cd-r2*r2)/(2.0*r1*sqrt(cd)) );
    105     p[0] = cir[ca].pt( base-delta );
    106     p[1] = cir[ca].pt( base+delta );
    107     return 2;
    108 }
    109 bool clinter( int c, long double xl, long double xr, Arc *arc ) {
    110     long double xlb = cir[c].c.x-cir[c].r;
    111     long double xrb = cir[c].c.x+cir[c].r;
    112     if( sg(xlb-xr)>=0 || sg(xrb-xl)<=0 ) return false;
    113     Point p = cir[c].c;
    114     long double r = cir[c].r;
    115     long double d1, d2;
    116     long double s1 = r*r-(p.x-xl)*(p.x-xl);
    117     long double s2 = r*r-(p.x-xr)*(p.x-xr);
    118     if( s1<0.0 ) s1=0.0;
    119     if( s2<0.0 ) s2=0.0;
    120     d1 = sqrt( s1 );
    121     d2 = sqrt( s2 );
    122     arc[0] = Arc( c, -1, Point(xr,p.y+d2), Point(xl,p.y+d1) );
    123     arc[1] = Arc( c, +1, Point(xl,p.y-d1), Point(xr,p.y-d2) );
    124     return true;
    125 }
    126 long double area( long double lf, long double rg ) {
    127     int m=0;
    128     for( int i=0; i<n; i++ ) 
    129         if( clinter(i,lf,rg,arc+m) ) 
    130             m += 2;
    131     sort( arc, arc+m, cmp_arc );
    132 
    133     int cc = 0, top;
    134     long double rt = 0.0;
    135     for( int i=0; i<m; i++ ) {
    136         if( cc==0 ) 
    137             top = i;
    138         cc += arc[i].type;
    139         if( cc==0 ) {
    140             rt += (rg-lf)*((arc[i].pa+arc[i].pb).y-(arc[top].pa+arc[top].pb).y)/2.0;
    141             rt += arc[top].area()+arc[i].area();
    142         }
    143     }
    144     return rt;
    145 }
    146 bool cmp_eq( long double x, long double y ) {
    147     return sg(x-y)==0;
    148 }
    149 void clean() {
    150     int j=0;
    151     for( int i=0; i<n; i++ )
    152         if( !del[i] ) cir[j++]=cir[i];
    153     n = j;
    154 }
    155 long double area() {
    156     Point ip[2];
    157     int ic;
    158     long double rt = 0.0;
    159     for( int i=0; i<n; i++ ) {
    160         for( int j=i+1; j<n; j++ ) {
    161             ic = ccinter( i, j, ip );
    162             if( ic<=1 ) continue;
    163             for( int k=0; k<ic; k++ ) {
    164                 int q=n;
    165                 for( q=0; q<n; q++ ) {
    166                     if( q==i || q==j ) continue;
    167                     if( cir[q].in(ip[k]) ) 
    168                         break;
    169                 }
    170                 if( q==n ) spt[stot++]=ip[k].x;
    171             }
    172         }
    173     }
    174     for( int i=0; i<n; i++ ) {
    175         spt[stot++] = cir[i].c.x-cir[i].r;
    176         spt[stot++] = cir[i].c.x+cir[i].r;
    177     }
    178     sort( spt, spt+stot );
    179     stot = unique( spt, spt+stot, cmp_eq ) - spt;
    180     
    181     for( int i=1; i<stot; i++ ) 
    182         rt += area( spt[i-1], spt[i] );
    183     return rt;
    184 }
    185 void init() {
    186     sort( cir, cir+n, cmp_cir_r );
    187     for( int i=0; i<n; i++ )
    188         for( int j=i+1; j<n; j++ ) {
    189             long double dx = cir[i].c.x-cir[j].c.x;
    190             long double dy = cir[i].c.y-cir[j].c.y;
    191             long double dij = dx*dx+dy*dy;
    192             long double cc = cir[j].r-cir[i].r;
    193             cc = cc*cc;
    194             if( dij<cc ) del[i]=true;
    195         }
    196     clean();
    197 }
    198 int main() {
    199     scanf( "%d", &n );
    200     for( int i=0; i<n; i++ ) 
    201         scanf( "%Lf%Lf%Lf", &cir[i].c.x, &cir[i].c.y, &cir[i].r );
    202     init();
    203     printf( "%.3Lf
    ", area() );
    204 }
    View Code
  • 相关阅读:
    Linux基础ls命令
    Linux基础tree命令
    Java银行调度系统
    Java交通灯系统
    Java反射
    Java基础IO流
    Java多线程
    Java集合框架
    Springmvc的一些属性功能
    JS
  • 原文地址:https://www.cnblogs.com/idy002/p/4421519.html
Copyright © 2011-2022 走看看