zoukankan      html  css  js  c++  java
  • NOI十连测 第六测 T3

     

    思路:考试的时候我非常地**,写了圆并,然后还TM写了半平面交和三角剖分,虽然只有30分。。但是看在我写了500行的份上还是挂着吧。。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 const double Pi=acos(-1);
      7 const double eps=1e-10;
      8 int n,m,cnt,tot,num;
      9 bool pd[200005],check;
     10 int read(){
     11     int t=0,f=1;char ch=getchar();
     12     while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
     13     while ('0'<=ch&&ch<='9') {t=t*10+ch-'0';ch=getchar();}
     14     return t*f;
     15 }
     16 struct node{
     17     double l,r;
     18 }L[200005];
     19 struct Point{
     20     double x,y;
     21     Point(){}
     22     Point(double x0,double y0):x(x0),y(y0){}
     23 }p[200005],c[200005],d[200005];
     24 struct Line{
     25     Point s,e;
     26     double slop;
     27     Line(){}
     28     Line(Point s0,Point e0):s(s0),e(e0){}
     29 }l[200005],q[200005];
     30 struct Circle{
     31     Point p;
     32     double r;
     33     Circle(){}
     34     Circle(double x0,double y0,double r0):p(Point(x0,y0)),r(r0){}    
     35 }a[200005];
     36 bool cmp2(node a,node b){
     37     if (fabs(a.l-b.l)<eps) return a.r<b.r;
     38     else return (a.l<b.l);
     39 }
     40 int sgn(double x){if (x>eps) return 1;if (x<-eps) return -1;return 0;}
     41 double operator *(Point p1,Point p2){return p1.x*p2.y-p1.y*p2.x;}
     42 double operator /(Point p1,Point p2){return p1.x*p2.x+p1.y*p2.y;}
     43 Point operator -(Point p1,Point p2){return Point(p1.x-p2.x,p1.y-p2.y);}
     44 Point operator +(Point p1,Point p2){return Point(p1.x+p2.x,p1.y+p2.y);}
     45 Point operator *(Point p1,double x){return Point(p1.x*x,p1.y*x);}
     46 Point operator /(Point p1,double x){return Point(p1.x/x,p1.y/x);}
     47 double sqr(double x){return x*x;}
     48 double llen(Point p1){return sqrt(sqr(p1.x)+sqr(p1.y));    }
     49 double dis(Point p1,Point p2){return llen(p1-p2);}
     50 double dis(Point p1){return llen(p1);}
     51 Point evector(Point p1){double t=llen(p1);if (t<eps) return Point(0,0);else return p1/t;}
     52 bool cmp3(Line p1,Line p2){
     53     if (p1.slop!=p2.slop) return p1.slop<p2.slop;
     54     else return (p1.e-p1.s)*(p2.e-p1.s)>0;
     55 }
     56 bool cmp(Point p1,Point p2){
     57     double t=(p1-p[1])*(p2-p[1]);
     58     if (fabs(t)<eps) return dis(p[1],p1)<dis(p[1],p2);
     59     return t>0;
     60 }
     61 bool conclude(Circle p1,Circle p2){
     62     double Len=dis(p1.p,p2.p);
     63     if (fabs(p1.r-p2.r)>=Len) return 1;
     64     return 0;
     65 }
     66 bool intersect(Circle p1,Circle p2){
     67     double Len=dis(p1.p,p2.p);
     68     if (fabs(p1.r-p2.r)<=Len&&Len<=p1.r+p2.r) return 1;
     69     return 0;
     70 }
     71 double dist_line(Line p){
     72     double A,B,C,dist;
     73     A=p.s.y-p.e.y;
     74     B=p.s.x-p.e.x;
     75     C=p.s.x*p.e.y-p.s.y*p.e.x;
     76     dist=fabs(C)/sqrt(sqr(A)+sqr(B));
     77     return dist;
     78 }
     79 double dist_line(Point p1,Line p){
     80     p.s.x-=p1.x;
     81     p.e.x-=p1.x;
     82     p.s.y-=p1.y;
     83     p.e.y-=p1.y;
     84     return dist_line(p);
     85 }
     86 double get_cos(double a,double b,double c){
     87     return (b*b+c*c-a*a)/(2*b*c);
     88 }
     89 double get_angle(Point p1,Point p2){
     90     if (!sgn(dis(p1))||!sgn(dis(p2))) return 0.0;
     91     double A,B,C;
     92     A=dis(p1);
     93     B=dis(p2);
     94     C=dis(p1,p2);
     95     if (C<=eps) return 0.0;
     96     return fabs(acos(get_cos(C,A,B)));
     97 }
     98 Point get_point(Point p){
     99     double T=sqr(p.x)+sqr(p.y);
    100     return Point(sgn(p.x)*sqrt(sqr(p.x)/T),sgn(p.y)*sqrt(sqr(p.y)/T));
    101 }
    102 bool bigconclude(Circle p1,Circle p2,Point p){
    103     Point e1=p2.p-p1.p;
    104     Point e2=p-p1.p;
    105     if (sgn(e1/e2)<0) return 1;
    106     else return 0;
    107 }
    108 double S(Point p1,Point p2,Point p3){
    109     return fabs((p2-p1)*(p3-p1))/2;
    110 }
    111 double work(Point p1,Point p2,double R){
    112     Point O=Point(0,0);
    113     double f=sgn(p1*p2),res=0;
    114     if (!sgn(f)||!sgn(dis(p1))||!sgn(dis(p2))) return 0.0;
    115     double l=dist_line(Line(p1,p2));
    116     double a=dis(p1);
    117     double b=dis(p2);
    118     double c=dis(p1,p2);
    119     if (a<=R&&b<=R){
    120         return fabs(p1*p2)/2.0*f;
    121     }
    122     if (a>=R&&b>=R&&l>=R){
    123         double ang=get_angle(p1,p2);
    124         return fabs((ang/(2.0))*(R*R))*f;
    125     }
    126     if (a>=R&&b>=R&&l<=R&&(get_cos(a,b,c)<=0||get_cos(b,a,c)<=0)){
    127         double ang=get_angle(p1,p2);
    128         return fabs((ang/(2.0))*(R*R))*f;
    129     }
    130     if (a>=R&&b>=R&&l<=R&&(get_cos(a,b,c)>0&&get_cos(b,a,c)>0)){
    131         double dist=dist_line(Line(p1,p2));
    132         double len=sqrt(sqr(R)-sqr(dist))*2.0;
    133         double ang1=get_angle(p1,p2);
    134         double cos2=get_cos(len,R,R);
    135         res+=fabs(len*dist/2.0);
    136         double ang2=ang1-acos(cos2);
    137         res+=fabs((ang2/(2))*(R*R));
    138         return res*f;
    139     }
    140     if ((a>=R&&b<R)||(a<R&&b>=R)){
    141         if (b>a) std::swap(a,b),std::swap(p1,p2);
    142         double T=sqr(p1.x-p2.x)+sqr(p1.y-p2.y);
    143         Point u=Point(sgn(p1.x-p2.x)*sqrt(sqr(p1.x-p2.x)/T),sgn(p1.y-p2.y)*sqrt(sqr(p1.y-p2.y)/T));
    144         double dist=dist_line(Line(p1,p2));
    145         double len=sqrt(R*R-dist*dist);
    146         double len2=sqrt(sqr(dis(p2))-sqr(dist));
    147         if (fabs(dis(p2+u*len2)-dist)<=eps) len+=len2;
    148         else len-=len2;
    149         Point p=p2+u*len;
    150         res+=S(O,p2,p);
    151         double ang=get_angle(p1,p);
    152         res+=fabs((ang/2.0)*R*R);
    153         return res*f;
    154     }
    155     return 0;
    156 }
    157 Point inter(Line p1,Line p2){
    158     double t1=(p2.e-p1.s)*(p1.e-p1.s);
    159     double t2=(p1.e-p1.s)*(p2.s-p1.s);
    160     if (fabs(t1+t2)<eps) check=1;
    161     double k=t1/(t1+t2);
    162     Point p;
    163     p.x=p2.e.x+(p2.s.x-p2.e.x)*k;
    164     p.y=p2.e.y+(p2.s.y-p2.e.y)*k;
    165     return p;
    166 }
    167 bool jud(Line p1,Line p2,Line p3){
    168     Point p=inter(p1,p2);
    169     return (p3.e-p3.s)*(p-p3.s)<0;
    170 }
    171 double inter(Circle P){
    172     double res=0;p[n+1]=p[1];
    173     for (int i=1;i<=n+1;i++)
    174      c[i].x=p[i].x-P.p.x,c[i].y=p[i].y-P.p.y;
    175     for (int i=1;i<=n;i++)
    176      res+=work(c[i],c[i+1],P.r);
    177     return res;
    178 }
    179 void hpi(){
    180     int L=1,R=0;tot=0;
    181     for (int i=1;i<=cnt;i++){
    182      if (l[i].slop!=l[i-1].slop) tot++;
    183      l[tot]=l[i];
    184     }
    185     q[++R]=l[1];q[++R]=l[2];
    186     int all=tot;
    187     for (int i=3;i<=all;i++){
    188         while (L<R&&jud(q[R],q[R-1],l[i])) R--;
    189         while (L<R&&jud(q[L],q[L+1],l[i])) L++;
    190         q[++R]=l[i];
    191     }
    192     while (L<R&&jud(q[R],q[R-1],q[L])) R--;
    193     while (L<R&&jud(q[L],q[L+1],q[R])) L++;
    194     tot=0;
    195     for (int i=L;i<R;i++)
    196      d[++tot]=inter(q[i],q[i+1]); 
    197 }
    198 bool judge(Point p1,Point p2){
    199     return (fabs(p1.x-p2.x)<eps&&fabs(p1.y-p2.y)<eps);
    200 }
    201 double gworking1(Point c1,Point c2,Point p1,Point p2){
    202     double rev=sgn(c1*c2);
    203     if (fabs(rev)<eps) return 0;
    204     num=0;
    205     Point O=Point(0,0);
    206     if ((c1*c2)<0) std::swap(c1,c2); 
    207     l[++num].s=O,l[num].e=c1;if (judge(l[num].s,l[num].e)) num--;
    208     l[++num].s=c1,l[num].e=c2;if (judge(l[num].s,l[num].e)) num--;
    209     l[++num].s=c2,l[num].e=O;if (judge(l[num].s,l[num].e)) num--;
    210     if ((p1*p2)<0) std::swap(p1,p2);
    211     l[++num].s=O,l[num].e=p1;if (judge(l[num].s,l[num].e)) num--;
    212     l[++num].s=p1,l[num].e=p2;if (judge(l[num].s,l[num].e)) num--;
    213     l[++num].s=p2,l[num].e=O;if (judge(l[num].s,l[num].e)) num--;
    214     for (int i=1;i<=num;i++)
    215      l[i].slop=atan2(l[i].e.y-l[i].s.y,l[i].e.x-l[i].s.x);
    216     std::sort(l+1,l+1+num,cmp3); 
    217     check=0;
    218     hpi();
    219     if (check) return 0;
    220     d[tot+1]=d[1];
    221     double res=0;
    222     for (int i=1;i<=tot;i++)
    223      res+=(d[i]*d[i+1])/2.0;
    224     return fabs(res)*rev; 
    225 }
    226 double Gworking1(double a1,double a2,Circle w){
    227     double r=w.r;
    228     Point p1=Point(r*cos(a1),r*sin(a1));
    229     Point p2=Point(r*cos(a2),r*sin(a2));
    230     p[n+1]=p[1];
    231     for (int i=1;i<=n+1;i++)
    232      c[i]=Point(p[i].x-w.p.x,p[i].y-w.p.y);
    233     double res=0;
    234     for (int i=1;i<=n;i++)
    235       res+=gworking1(c[i],c[i+1],p1,p2);
    236     return res;  
    237 }
    238 Point inter(Circle p,Line l,Point p1){
    239     double Dist=dist_line(l);
    240     double dis1=llen(p1);
    241     double len=sqrt(sqr(dis1)-sqr(Dist));
    242     Point e=evector(l.e-l.s);
    243     Point sx=p1;
    244     double R=p.r;
    245     double len2=sqrt(sqr(R)-sqr(Dist));
    246     sx=sx-e*len;
    247     sx=sx+e*len2;
    248     return sx;
    249 }
    250 double gworking2(Point c1,Point c2,Point p1,Point p2,double R){
    251     double rev=sgn(c1*c2),res=0;Point O=Point(0,0);
    252     if ((p1*p2)<0) std::swap(p1,p2);
    253     if ((c1*c2)<0) std::swap(c1,c2);
    254     if (fabs(rev)<eps) return 0; 
    255     if (!sgn(dis(p1))||!sgn(dis(p2))) return 0.0;
    256     double l=dist_line(Line(p1,p2));
    257     double a=dis(p1);
    258     double b=dis(p2);
    259     double c=dis(p1,p2);
    260     if (a<=R&&b<=R){
    261         res=fabs(p1*p2)/2.0;
    262     }
    263     else
    264     if (a>=R&&b>=R&&l>=R){
    265         double ang=get_angle(p1,p2);
    266         res=abs((ang/(2.0))*(R*R));
    267     }
    268     else
    269     if (a>=R&&b>=R&&l<=R&&(get_cos(a,b,c)<=0||get_cos(b,a,c)<=0)){
    270         double ang=get_angle(p1,p2);
    271         res=fabs((ang/(2.0))*(R*R));
    272     }
    273     else
    274     if (a>=R&&b>=R&&l<=R&&(get_cos(a,b,c)>0&&get_cos(b,a,c)>0)){
    275         double dist=dist_line(Line(p1,p2));
    276         double len=sqrt(sqr(R)-sqr(dist))*2.0;
    277         double ang1=get_angle(p1,p2);
    278         double cos2=get_cos(len,R,R);
    279         res+=fabs(len*dist/2.0);
    280         double ang2=ang1-acos(cos2);
    281         res+=fabs((ang2/(2))*(R*R));
    282     }
    283     else
    284     if ((a>=R&&b<R)||(a<R&&b>=R)){
    285         if (b>a) std::swap(a,b),std::swap(p1,p2);
    286         double T=sqr(p1.x-p2.x)+sqr(p1.y-p2.y);
    287         Point u=Point(sgn(p1.x-p2.x)*sqrt(sqr(p1.x-p2.x)/T),sgn(p1.y-p2.y)*sqrt(sqr(p1.y-p2.y)/T));
    288         double dist=dist_line(Line(p1,p2));
    289         double len=sqrt(R*R-dist*dist);
    290         double len2=sqrt(sqr(dis(p2))-sqr(dist));
    291         if (fabs(dis(p2+u*len2)-dist)<=eps) len+=len2;
    292         else len-=len2;
    293         Point p=p2+u*len;
    294         res+=S(O,p2,p);
    295         double ang=get_angle(p1,p);
    296         res+=fabs((ang/2.0)*R*R);
    297     }
    298     int in1=((sgn(c1*p1)*sgn(p1*c2))>=0);
    299     int in2=((sgn(c1*p2)*sgn(p2*c2))>=0);
    300     if (in1&&in2) return res*rev;
    301     if (!in1){
    302         if (dis(p1)<=R){
    303           Point sb=inter(Line(O,c1),Line(p1,p2));
    304           double Di=dis(sb);
    305           if (Di<=R) res-=S(O,sb,p1);
    306           else{
    307           Point sx=inter(Circle(0,0,R),Line(p1,p2),p1);    
    308           double ang=get_angle(c1,sx);
    309           res-=fabs((ang/2.0)*R*R);
    310           res-=S(O,sx,p1);
    311           }
    312         }else{
    313           Point sb=inter(Line(O,c1),Line(p1,p2));
    314           double Di=dis(sb);
    315           if (Di>=R){
    316             double ang=get_angle(c1,p1);
    317             res-=fabs((ang/2.0)*R*R);
    318           }else{
    319             Point sx=inter(Circle(0,0,R),Line(p1,p2),p1);
    320             double ang2=get_angle(p1,sx);
    321             res-=fabs((ang2/2.0)*R*R);
    322             res-=S(sb,sx,O);
    323           }
    324         }
    325     }
    326     if (!in2){
    327         if (dis(p2)<=R){
    328           Point sb=inter(Line(O,c2),Line(p1,p2));
    329           double Di=dis(sb);
    330           if (Di<=R) res-=S(O,sb,p2);
    331           else{
    332           Point sx=inter(Circle(0,0,R),Line(p2,p1),p2);    
    333           double ang=get_angle(c2,sx);
    334           res-=fabs((ang/2.0)*R*R);
    335           res-=S(O,sx,p2);
    336           }
    337         }else{
    338           Point sb=inter(Line(O,c2),Line(p1,p2));
    339           double Di=dis(sb);
    340           if (Di>=R){
    341             double ang=get_angle(c2,p2);
    342             res-=fabs((ang/2.0)*R*R);
    343           }else{
    344             Point sx=inter(Circle(0,0,R),Line(p2,p1),p2);
    345             double ang2=get_angle(p2,sx);
    346             res-=fabs((ang2/2.0)*R*R);
    347             res-=S(sb,sx,O);
    348           }
    349         }
    350     }
    351     return res*rev;
    352 }
    353 double Gworking2(double a1,double a2,Circle w){
    354     double res=0,r=w.r;
    355     Point p1=Point(r*cos(a1),r*sin(a1));
    356     Point p2=Point(r*cos(a2),r*sin(a2));
    357     p[n+1]=p[1];
    358     for (int i=1;i<=n+1;i++)
    359      c[i]=Point(p[i].x-w.p.x,p[i].y-w.p.y);
    360     for (int i=1;i<=n;i++)
    361       res+=gworking2(c[i],c[i+1],p1,p2,r); 
    362     return res;
    363 }
    364 void graham(){
    365     int k=1;
    366     for (int i=2;i<=n;i++)
    367      if (p[i].y<p[k].y||(p[i].x<p[k].x&&p[i].y==p[k].y)) k=i;
    368     std::sort(p+2,p+1+n,cmp);
    369     int top=1;c[top]=p[1];
    370     for (int i=2;i<=n;i++){
    371         while (top>1&&(c[top]-c[top-1])*(p[i]-c[top])<=0) top--;
    372         c[++top]=p[i]; 
    373     }
    374     n=top;
    375     for (int i=1;i<=top;i++)
    376      p[i]=c[i];
    377 }
    378 void Work(Circle p1,Point a1,Point a2){
    379     Point O=p1.p;double r=p1.r;
    380     a1.x-=O.x;a2.x-=O.x;
    381     a1.y-=O.y;a2.y-=O.y;
    382     double x1=atan2(a1.y,a1.x),x2=atan2(a2.y,a2.x);
    383     if (x1<0) x1+=2*Pi;
    384     if (x2<0) x2+=2*Pi;
    385     if (x1<=x2){
    386         cnt++;
    387         L[cnt].l=x1;
    388         L[cnt].r=x2;
    389     }else{
    390         cnt++;
    391         L[cnt].l=x1;
    392         L[cnt].r=2*Pi;
    393         cnt++;
    394         L[cnt].l=0.0;
    395         L[cnt].r=x2;
    396     }
    397 }
    398 void add(Circle p1,Circle p2){
    399     double x1=p1.p.x,x2=p2.p.x,y1=p1.p.y,y2=p2.p.y,r1=p1.r,r2=p2.r;
    400     double A=-2*(x1+x2),B=-2*(y1+y2),C=sqr(x1)+sqr(x2)+sqr(y1)+sqr(y2)-sqr(r1)-sqr(r2);
    401     Point S,E;
    402     if (fabs(A)<eps){
    403         S=Point(1,(C)/B);
    404         E=Point(2,(C)/B);
    405     }else
    406     if (fabs(B)<eps){
    407         S=Point((C)/A,1);
    408         E=Point((C)/A,2);
    409     }else{
    410         S=Point(1,(C-A)/B);
    411         E=Point(2,(C-2*A)/B);
    412     }
    413     Line l=Line(S,E);
    414     double Dist1=dist_line(p1.p,l);
    415     double Dist2=llen(p1.p-S);
    416     Point e=evector(E-S);
    417     double Dist3=sqrt(sqr(Dist2)-sqr(Dist1));
    418     e=e*Dist3;
    419     Point a1,a2;
    420     if (fabs(dis(S+e,p1.p)-Dist1)<eps){
    421         S=S+e;
    422     }
    423     else S=S-e;
    424     e=e/Dist3;
    425     double Dist4=sqrt(sqr(p1.r)-sqr(llen(S-p1.p)));
    426     e=e*Dist4;
    427     a1=S+e;
    428     a2=S-e;
    429     if ((a1-p1.p)*(a2-p1.p)<0) std::swap(a1,a2);
    430     //a1放在a2的顺时针方向、 
    431     if (bigconclude(p1,p2,a1)) std::swap(a1,a2);
    432     //a1到a2必须是逆时针。
    433     Work(p1,a1,a2); 
    434 }
    435 int main(){
    436     freopen("aerolite.in","r",stdin);
    437     freopen("aerolite.out","w",stdout);
    438     scanf("%d",&m);
    439     for (int i=1;i<=m;i++){
    440         scanf("%lf%lf%lf",&a[i].p.x,&a[i].p.y,&a[i].r);
    441     }
    442     scanf("%d",&n);
    443     for (int i=1;i<=n;i++){
    444         scanf("%lf%lf",&p[i].x,&p[i].y);
    445     }
    446     graham();
    447     for (int i=1;i<=m;i++) pd[i]=1;
    448     for (int i=1;i<=m;i++){
    449      for (int j=1;j<=m;j++)
    450       if (i!=j){
    451         if (conclude(a[i],a[j])) {pd[i]=0;break;}    
    452       }
    453     }
    454     double ans=0;
    455     for (int i=1;i<=m;i++)
    456      if (pd[i]){
    457       bool mark=0;
    458       for (int j=1;j<=m;j++)
    459        if (i!=j&&pd[j]){
    460          if (intersect(a[i],a[j])) {mark=1;break;}
    461        }  
    462       if (!mark) ans+=inter(a[i]),pd[i]=0; 
    463     } 
    464     int j=0;
    465     for (int i=1;i<=m;i++)
    466      if (pd[i]) a[++j]=a[i];
    467     for (int i=1;i<=m;i++) pd[i]=1; 
    468     for (int i=1;i<=m;i++){
    469         cnt=0;
    470         for (int j=1;j<=m;j++)
    471          if (i!=j){
    472             add(a[i],a[j]);    
    473         }
    474         std::sort(L+1,L+1+cnt,cmp2);
    475         L[0].r=0.0;
    476         L[cnt+1].l=2*Pi;
    477         double Reach=0.0,Last=0.0;
    478         int ww=0;
    479         for (int j=1;j<=cnt;j++)
    480          if (L[j].l>Reach){
    481                 if (j==126) ww++;
    482                 ans+=Gworking1(Last,Reach,a[i]);
    483                 Last=L[j].l;
    484                 ans+=Gworking2(Reach,L[j].l,a[i]);
    485                 Reach=L[j].r;
    486          }else{
    487                 Reach=L[j].r;
    488          }
    489          if (fabs(Reach-2*Pi)<eps){
    490                 ans+=Gworking1(Last,Reach,a[i]);
    491          }else
    492          if (fabs(Reach-2*Pi)>=eps){
    493                 ans+=Gworking1(Last,Reach,a[i]);
    494                 ans+=Gworking2(Reach,2*Pi,a[i]);
    495          }
    496     }
    497     printf("%.8lf
    ",ans);
    498     return 0;
    499 }
  • 相关阅读:
    手机号码正则(已测试可以)
    查看phpfpm的进程和端口号
    JS正则表达式验证是否为11位有效手机号码,
    访问HTML可以,访问PHPfile not found
    戏说论文、技术文档与网络文字的区别
    Sun 一线产品的图标
    VC编程中如何设置对话框的背景颜色和静态文本颜色
    Sun 一线产品的图标
    Web Beans首个预览版发布
    Web Beans首个预览版发布
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5607161.html
Copyright © 2011-2022 走看看