【模板】多圆面积并

链接:https://vjudge.net/problem/SPOJ-CIRU

辛普森积分:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1000+9;
 4 #define eps 1e-6
 5 #define inf 0x3f3f3f3f
 6 struct Cir{
 7     double x,y,r;
 8 }c[N],tmp[N];
 9 pair<double,double> seg[N];
10 bool cmp2(Cir a,Cir b){return a.r > b.r;}
11 bool cmp(Cir a,Cir b){
12     return (fabs(a.x - a.r - b.x + b.r ) < eps) ? a.x + a.r < b.x + b.r : a.x - a.r < b.x - b.r;
13 }
14 bool in_cir(Cir a,Cir b){
15     return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) <= (a.r -b.r) * (a.r - b.r);
16 }
17 int n,st,ed; 
18 void prework(){
19     sort(c+1,c+1+n,cmp2);
20     int cnt = 0;
21     for(int i = 1;i<=n;++i){
22         bool ok = 1;
23         for(int j = 1;j<=cnt;++j){
24             if(in_cir(c[i],c[j])){
25                 ok = 0;
26                 break;
27             }
28         }
29         if(ok) tmp[++cnt] = c[i];
30     }
31     n = cnt;
32     memcpy(c,tmp,sizeof(tmp));
33 }
34 double getf(double x){
35     int tot = 0;
36     for(int i = st;i<=ed;++i){
37         if(x < c[i].x + c[i].r && x > c[i].x - c[i].r){
38             double len = sqrt(c[i].r * c[i].r - ( x -c[i].x ) * (x - c[i].x) );
39             seg[++tot] = make_pair(c[i].y-len,c[i].y + len);
40         }
41     }
42     sort(seg+1,seg+1+tot);
43     double ans = 0,segl = -inf ,segr = -inf;
44     for(int i = 1;i<=tot;++i){
45         if(seg[i].first >= segr){
46             ans += segr - segl;
47             segl = seg[i].first;
48             segr = seg[i].second;
49         }
50         else segr = max(segr,seg[i].second);
51     }
52     ans += segr - segl;
53     return ans;
54 }
55 double calc(double len,double fL,double fM,double fR){
56     return (fL + 4*fM + fR) * len / 6;
57 }
58 double Simpson(double L,double M,double R,double fL,double fM,double fR,double sum){
59     double M1 = (L+M)/2 , M2 = (M+R)/2;
60     double fM1 = getf(M1), fM2 = getf(M2);
61     double g1 = calc(M-L,fL,fM1,fM) , g2 = calc(R-M,fM,fM2,fR);
62     if(fabs(sum - g1 - g2) <= eps ) return g1 + g2;
63     return Simpson(L,M1,M,fL,fM1,fM,g1) + Simpson(M,M2,R,fM,fM2,fR,g2);
64 }
65 void solve(){
66     sort(c+1,c+1+n,cmp);
67     double ans = 0;
68     for(int i = 1;i<=n;++i){
69         double L = c[i].x - c[i].r , R = c[i].x + c[i].r;
70         int j;
71         for(j = i+1;j<=n;++j){
72             if(c[j].x - c[j].r > R) break;
73             else R = max(R,c[j].x + c[j].r);
74         }
75         double M = (L+R)/2;
76         st = i,ed = j-1;
77         i = j-1;
78         double fL = getf(L),fM = getf(M),fR = getf(R);
79         ans += Simpson(L,M,R,fL,fM,fR,calc(R-L,fL,fM,fR));
80     }
81     printf("%.3f\n",ans);
82 }
83 int main(){
84     scanf("%d",&n);
85     for(int i = 1;i<=n;++i) scanf("%lf %lf %lf",&c[i].x,&c[i].y,&c[i].r);
86     prework();
87     solve();
88 }
View Code

猜你喜欢

转载自www.cnblogs.com/xiaobuxie/p/11962302.html