【计算几何】bzoj1043 [HAOI2008]下落的圆盘
n^2枚举圆盘,用两圆圆心的向量的极角+余弦定理求某个圆覆盖了该圆的哪一段区间(用弧度表示),最后求个区间并。
注意……精度……最好再累计区间的时候,把每个区间的长度减去EPS,防止最后覆盖的总区间超过2PI一点点,使答案为负。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define EPS 0.000000001 #define INF 1000000.0 int n; const double PI= acos (-1.0); double rs[1001],xs[1001],ys[1001],ans; struct Seg { double l,r; Seg(){} Seg( const double &L, const double &R){l=L; r=R;} }q[10001]; bool cmp( const Seg &a, const Seg &b) { return fabs (a.l-b.l)<EPS ? a.r<b.r : a.l<b.l; } double sqr( const double &x) { return x*x; } double dis( double x1, double y1, double x2, double y2) { return sqrt (sqr(x1-x2)+sqr(y1-y2)); } int main() { // freopen("bzoj1043.in","r",stdin); scanf ( "%d" ,&n); for ( int i=1;i<=n;++i) scanf ( "%lf%lf%lf" ,&rs[i],&xs[i],&ys[i]); for ( int i=1;i<=n;++i) { int e=0; double Lef=2.0*PI; for ( int j=i+1;j<=n;++j) { double d=dis(xs[i],ys[i],xs[j],ys[j]); if (d+rs[i]-rs[j]<EPS) { Lef=0.0; break ; } else if (d+rs[j]-rs[i]<EPS || rs[i]+rs[j]-d<-EPS) continue ; // double see=(sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i]; double jiao2= acos ((sqr(d)+sqr(rs[i])-sqr(rs[j]))*0.5/d/rs[i]); double jiao1= atan2 (ys[j]-ys[i],xs[j]-xs[i]); if (jiao1<-EPS) jiao1+=(2.0*PI); if (jiao1-jiao2<-EPS) { q[++e]=Seg(0.0,jiao1+jiao2); q[++e]=Seg(jiao1-jiao2+2.0*PI,2.0*PI); } else if (jiao1+jiao2-2.0*PI>EPS) { q[++e]=Seg(jiao1-jiao2,2.0*PI); q[++e]=Seg(0.0,jiao1+jiao2-2.0*PI); } else q[++e]=Seg(jiao1-jiao2,jiao1+jiao2); } // for(int j=e;j;--j) // { // bool fl=0; // for(int k=j-1;k;--k) // if(!(q[j].l-q[k].r>EPS||q[k].l-q[j].r>EPS)) // { // q[k].l=min(q[j].l,q[k].l); // q[k].r=max(q[j].r,q[k].r); // fl=1; // break; // } // if(!fl) // Lef-=(q[j].r-q[j].l); // } Seg now=Seg(INF,INF); sort(q+1,q+e+1,cmp); for ( int j=1;j<=e;++j) if (j==e || q[j+1].l-q[j].l>EPS) { if ( fabs (now.l-INF)<EPS) now=q[j]; else { if (q[j].l-now.r<EPS) now.r=max(now.r,q[j].r); else { Lef-=(now.r-now.l); now=q[j]; } } } if ( fabs (now.l-INF)>=EPS) Lef-=(now.r-now.l); if (Lef>EPS) ans+=(Lef*rs[i]); } printf ( "%.3lf\n" ,ans); return 0; } |
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步