[BZOJ2178]圓的面積並
前不久看到格林公式這個東西,想到了這道題,當時還不太懂要怎麽處理,直到最近看到了n+e的博客
設$D$為一個平面單連通區域,$L$是它的取正向的輪廓線(分段光滑),$P,Q$在$D$上具有一階連續偏導數,則有格林公式
$\iint\limits_D\left(\frac{\partial Q}{\partial x}-\frac{\partial P}{\partial y}\right)\mathrm dx\mathrm dy=\oint_LP\mathrm dx+Q\mathrm dy$
證明的話直接按定義分別算$P$和$Q$的部分就可以了,一點都不藝術(霧
在這個公式中,取$Q=x,P=-y$,我們得到$\iint\limits_D2\mathrm dx\mathrm dy=\oint_L-y\mathrm dx+x\mathrm dy$,即是說$D$的面積為$\frac12\oint_L-y\mathrm dx+x\mathrm dy$
這樣有個好,就是能把面積轉化為跟輪廓線有關的計算
在這題中,我們只需要把所有圓的能夠成最後圖形的輪廓線的弧找出來做曲線積分,求和即可
圓$C:(x-x_0)^2+(y-y_0)^2=r^2$上一段弧$L$的參數方程為$\begin{cases}x=x_0+r\cos t\\y=y_0+r\sin t\end{cases}(\theta_1\leq t\leq\theta_2)$
$\begin{align*}\oint_L-y\mathrm dx+x\mathrm dy&=\int_{\theta_1}^{\theta_2}-(y_0+r\sin t)\mathrm d(x_0+r\cos t)+(x_0+r\cos t)\mathrm d(y_0+r\sin t)\\&=\int_{\theta_1}^{\theta_2}r^2+ry_0\sin t+rx_0\cos t\mathrm dt\\&=\left.\left(r^2\theta-ry_0\cos t+rx_0\sin t\right)\right|_{\theta_1}^{\theta_2}\end{align*}$
然後就做完了,時間復雜度$O\left(n^2\log_2n\right)$
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; typedef double du; const du pi2=M_PI*2; struct point{ du x,y; point(du a=0,du b=0){x=a;y=b;} du len(){return sqrt(x*x+y*y);} }; point operator-(point a,point b){return point(a.x-b.x,a.y-b.y);} bool operator<(point a,point b){return a.x==b.x?a.y<b.y:a.x<b.x;} bool operator==(point a,point b){return a.x==b.x&&a.y==b.y;} struct circle{ point o; du r; du oint(du t1,du t2){return r*(r*(t2-t1)+o.x*(sin(t2)-sin(t1))-o.y*((cos(t2)-cos(t1))));} }c[1010]; bool operator<(circle a,circle b){return a.o==b.o?a.r<b.r:a.o<b.o;} bool operator==(circle a,circle b){return a.o==b.o&&a.r==b.r;} struct angle{ du a; int d; angle(du x=0,int y=0){a=x;d=y;} }p[2010]; bool operator<(angle a,angle b){return a.a<b.a;} int n; du solve(int u){ int i,M,cnt; du len,an,f,l,r,s; point d; cnt=0; M=0; for(i=1;i<=n;i++){ if(i!=u){ d=c[i].o-c[u].o; len=d.len(); if(c[u].r+len<=c[i].r)return 0; if(c[u].r>=c[i].r+len||len>=c[i].r+c[u].r)continue; an=atan2(d.y,d.x); f=acos((c[u].r*c[u].r+len*len-c[i].r*c[i].r)/(2*c[u].r*len)); l=an-f; r=an+f; if(l<-M_PI)l+=pi2; if(r>M_PI)r-=pi2; if(l>r)cnt++; p[++M]=angle(l,1); p[++M]=angle(r,-1); } } p[0]=-M_PI; p[++M]=M_PI; sort(p+1,p+M+1); s=0; for(i=1;i<=M;cnt+=p[i++].d){ if(cnt==0)s+=c[u].oint(p[i-1].a,p[i].a); } return s*.5; } int main(){ int i; du s; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r); sort(c+1,c+n+1); n=unique(c+1,c+n+1)-c-1; for(i=1;i<=n;i++)s+=solve(i); printf("%.3lf",s); }
[BZOJ2178]圓的面積並