[Explanations] CIRU - The area of the union of circles [SP8073] \ area of a circle and [Bzoj2178]

[Explanations] CIRU - The area of ​​the union of circles [SP8073] area of ​​a circle and [Bzoj2178]

Portal:

Description [title]

Given \ (n-\) round the center coordinates \ ((x, y) \ ) and the radius \ (R & lt \) , find the total area they cover.

[Enter]

A first line integer \ (n-\) , represents a total of \ (n-\) round, the next \ (n-\) each row three rows integer \ (X, Y, R & lt \) .

[Output]

Answers to three decimal places.

[Sample]

样例输入:
3
0 0 1
0 0 1
100 100 1

样例输出:
6.283

【data range】

\(100 \%:\) \(1 \leqslant n \leqslant 1000,\) \(|x|,|y| \leqslant 1000,\) \(0 \leqslant r \leqslant 1000\)

【analysis】

[Computational Geometry family bucket]

And area of ​​a circle of board title.

[Front] Cheese

Simpson adaptive integration (Messing around)

I do not know integration is something, but the teacher said as long as the back-up formula and will use it to find the area can be a: \ (ANS (L, r) = \ FRAC {(RL) (f_L + 4F_ {MID} + F_r) {6}} \) .

When calculating the area of a plane figure, \ (F_Y \) is the straight line \ (y = Y \) through the length of the portion of the pattern.

Example: a substrate for the \ (A \) , height \ (H \) of the area of the triangle can be represented as: \ (S = \ {H FRAC * (. 4 + A * \ FRAC} {2} {A +0) . 6} = {} \ FRAC * {A} H {2} \) . Below, \ (rl is an = H, A = f_L, F_ {MID} = \ FRAC {A} {2}, F_r = 0 \) :

(Further, when calculating the three-dimensional graphics volume, \ (F_Y \) is plane \ (the Y = Z \) . The area of the portion passing through the pattern Example: a radius (R & lt \) \ sphere volume can be expressed as: \ (V = \ {2R FRAC * (0 +. 4 \ R & lt PI ^ 2 + 0)}. 6} = {\ {FRAC. 4 \ ^ R & lt PI. 3. 3} {} \) )

But not all of the graphics can be done like this, when such a problem will be of circular area (radius is \ (R & lt \) ): \ (S = \ {FRAC 2R * (2R *. 4 + 0 + 0 )}. 6} = {\ R & lt FRAC. 4 {^ {2}}. 3 \ NEQ \ R & lt PI ^ 2 \) .

This time it is necessary to use an adaptive Simpson's method : respectively the formula \ (ans (l, mid) \) and \ (ANS (MID, R & lt) \) , and if the sum of the two \ (ans (l, r ) \) differ by less than \ (EPS \) , returns \ (ANS (L, R & lt) \) , or recursive solution \ ((l, mid) \ ) and \ ((mid, r) \ ) plus stand up.

code show as below:

#define LD double
#define Rd register LD
inline LD F(Rd Y){return ???;}//视情况而定
inline LD Simpson(Rd L,Rd R){return (R-L)*(F(L)+4.0*F((L+R)*0.5)+F(R))/6.0;}//套公式
inline LD sakura(Rd L,Rd R,Rd now){//求解ans(L,R)
    Rd mid=(L+R)*0.5,FL=Simpson(L,mid),FR=Simpson(mid,R);//先用公式求左右两边
    if(!dcmp(now-FL-FR))return now;//满足精度要求
    return sakura(L,mid,FL)+sakura(mid,R,FR);//递归求解并求和
}

[Problem-solving]

Back to this question, the uppermost end points determined by side \ (Y_ {min}, Y_ {max} \) direct recursion can be solved, as the above \ (F. \) Function can enumerate all round intersection violence chord, then ordering them to do the line covered.

Note that accuracy should be fine, \ (\ text {Bzoj} \) requires \ (1E \ -! \ 13 is \!) , \ (\ Text {SPOJ} \) requires \ (1E \ -! \. 7 \!) .

Time complexity: \ (O (nlogn \ Times \) metaphysics \ () \) . The "metaphysics" as \ (F \) function call number.

【optimization】

Simply solved \ ((Y_ {min}, Y_ {max}) \) is \ (\ text {Bzoj} \ ) of the [abnormal cancer Data] card out, \ (\ text {SPOJ} \) also had can not.

why?

If \ (1 \) a circle at the top alone, \ (999 \) round the stack at the bottom, the last calculated error is very large, so segmentation process , i.e. all the circle is divided into several blocks Unicom solving respectively (which may be vertical endpoints of each circle segment covers put together to run), so that the error will be smaller sub.

At this abnormal cancer [data] successfully forget it, but it took \ (30s \) , consider \ (F \) functions of memory, then after a Boca often, the machine \ (10.6s \) , card just to pay up too.

[Re-optimization]

So, even [octamer oxygen] can not save the \ (\ text {SPOJ} \ ) how should we do?

Pretreatment in advance a large circle comprising small round case (small round contained deleted), greatly reduced (nlogn \) \ portion consumption.

Whirring, finally passed

【Code】

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#define LD double
#define LL long long
#define Re register int
#define Rd register LD
#define Vector Point
using namespace std;
const int N=2003;
const LD eps=1e-13;
int n,m;map<LD,LD>vis;
inline int dcmp(Rd a){return a<-eps?-1:(a>eps?1:0);}
struct Point{
    LD x,y;Point(LD X=0,LD Y=0){x=X,y=Y;}
    inline void in(){scanf("%lf%lf",&x,&y);}
};
struct Segment{
    LD L,R;Segment(LD l=0,LD r=0){L=l,R=r;}
    inline bool operator<(Segment O)const{return L!=O.L?L<O.L:R<O.R;}
}Seg[N];
struct Circle{
    LD x,y,r,L,R,D,U;
    inline void in(){scanf("%lf%lf%lf",&x,&y,&r),L=x-r,R=x+r,D=y-r,U=y+r;}
    inline bool operator<(Circle B)const{return D<B.D;}//按下端点排序
}C[N],C_[N];
inline bool cmp(Circle A,Circle B){return A.r<B.r;}//按半径排序
inline LD dis(Circle A,Circle B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
inline LD SS(Rd x){return x*x;}
inline LD F(Rd Y){
    if(vis[Y])return vis[Y];//记忆化
    Re t=0;Rd ans=0;
    for(Re i=1;i<=n;++i)
        if(dcmp(Y-C[i].D)>0&&dcmp(Y-C[i].U)<0){//如果直线穿过了该圆
            Rd tmp=sqrt(SS(C[i].r)-SS(C[i].y-Y));//勾股定理求交弦
            if(dcmp(tmp)>0)Seg[++t]=Segment(C[i].x-tmp,C[i].x+tmp);
        }
    if(!t)return 0.0;
    sort(Seg+1,Seg+t+1);
    for(Re i=1,j;i<=t;i=j+1){
        Rd L=Seg[i].L,R=Seg[i].R;j=i;
        while(j<t&&Seg[j+1].L<=R)++j,R=max(R,Seg[j].R);
        ans+=R-L;
    }
    return vis[Y]=ans;
}
inline LD Simpson(Rd L,Rd R){return (R-L)*(F(L)+4.0*F((L+R)*0.5)+F(R))/6.0;}//【辛普森公式】
inline LD sakura(Rd L,Rd R,Rd now){//【自适应】
    Rd mid=(L+R)*0.5,FL=Simpson(L,mid),FR=Simpson(mid,R);
    if(!dcmp(now-FL-FR))return now;
    return sakura(L,mid,FL)+sakura(mid,R,FR);
}
LD ans;
int main(){
//  freopen("789.txt","r",stdin);
    scanf("%d",&m);
    for(Re i=1;i<=m;++i)C_[i].in();
    sort(C_+1,C_+m+1,cmp),C[++n]=C_[m];//按半径大小排序
    for(Re i=m-1;i>=1;--i){//【大圆吃小圆】从大圆向小圆枚举
        Re flag=1;
        for(Re j=1;j<=n&&flag;++j)
            if(dcmp(C_[i].r-C[j].r+dis(C_[i],C[j]))<=0)flag=0;//小r+大r <= dis,则说明小圆C_[i]被包含了在了C[j]以内
        if(flag)C[++n]=C_[i];//C_[i]没有被大圆包含
    }
    sort(C+1,C+n+1);
    for(Re i=1,j;i<=n;i=j+1){//【分段处理】每个联通块单独处理
        Rd D=C[i].D,U=C[i].U;j=i;
        while(j<n&&C[j+1].D<=U)++j,U=max(U,C[j].U);
        ans+=sakura(D,U,Simpson(D,U));
    }
    printf("%.3lf",ans);
}

Guess you like

Origin www.cnblogs.com/Xing-Ling/p/12109559.html