【模板】多圆面积并
链接: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],tmp[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 }
格林公式:
参考:https://www.cnblogs.com/jefflyy/p/9247686.html
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1000+9; 4 const double PI = acos(-1.0); 5 struct Point{ 6 double x,y; 7 bool operator < (const Point& b)const{ 8 return x<b.x || (x==b.x && y<b.y); 9 } 10 bool operator == (const Point& b)const{ 11 return x==b.x && y == b.y; 12 } 13 Point operator - (const Point& b)const{ 14 return (Point){x - b.x,y - b.y}; 15 } 16 double len(){return sqrt(x*x + y*y);} 17 }; 18 struct Cir{ 19 Point o; 20 double r; 21 bool operator < (const Cir& b)const{ 22 return o<b.o || (o==b.o && r<b.r); 23 } 24 bool operator == (const Cir& b)const{ 25 return o == b.o && r == b.r; 26 } 27 double oint(double t1,double t2){ 28 return r*(r*(t2 - t1) + o.x * (sin(t2) - sin(t1)) - o.y * (cos(t2) - cos(t1))); 29 } 30 }c[N],tmp[N]; 31 pair<double,int> st[N<<1]; 32 int n; 33 double calc(int id){ 34 int top = 0, cnt = 0; 35 for(int i = 1;i<=n;++i){ 36 if(i != id){ 37 Point d = c[i].o - c[id].o; 38 double dis = d.len(); 39 if(c[id].r + dis <= c[i].r) return 0; 40 if(c[i].r + dis <= c[id].r) continue; 41 if(dis >= c[i].r + c[id].r) continue; 42 double ang = atan2(d.y,d.x); 43 double deta = acos( (c[id].r * c[id].r + dis * dis - c[i].r * c[i].r) / (2 * c[id].r * dis)); 44 double l = ang - deta, r = ang + deta; 45 if( l < -PI ) l += 2*PI; 46 if( r >= PI ) r -= 2*PI; 47 if( l > r ) ++cnt; 48 st[++top] = make_pair(l,1); 49 st[++top] = make_pair(r,-1); 50 } 51 } 52 st[0] = make_pair(-PI,0); 53 st[++top] = make_pair(PI,0); 54 sort(st+1,st+1+top); 55 double res = 0; 56 for(int i = 1;i<=top;cnt += st[i++].second){ 57 if(!cnt) res += c[id].oint(st[i-1].first,st[i].first); 58 59 } 60 return res; 61 } 62 int main(){ 63 scanf("%d",&n); 64 for(int i = 1;i<=n;++i) scanf("%lf %lf %lf",&c[i].o.x,&c[i].o.y,&c[i].r); 65 sort(c+1,c+1+n); n = unique(c+1,c+1+n) - c - 1; 66 double ans = 0; 67 for(int i = 1;i<=n;++i) ans += calc(i); 68 ans *= 0.5; 69 printf("%.3lf",ans); 70 return 0; 71 }

浙公网安备 33010602011771号