BZOJ2178:圆的面积并——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2178
给出N个圆,求其面积并。
simpson,将圆劈成两半,假设上面的叫上壳,下面的叫下壳,对这两个壳分别做一遍simpson,相减就是答案。
当然优化时间可以去掉完全包含的圆。
以及相减的时候注意同一坐标的不同解,我们要求他的并。
另外精度死活调不对,参考了:https://www.cnblogs.com/SfailSth/p/6360277.html的代码才过orz
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef double dl; const int N=1010; const dl eps=1e-8; const dl INF=2000; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct cir{ int x,y,r; }p[N]; int n,tag[N]; struct node{ dl l,r; }q[N]; inline bool cmp1(node a,node b){ return a.l<b.l||(a.l==b.l&&a.r<b.r); } inline bool cmp2(cir a,cir b){ return a.r<b.r; } inline dl f(dl x){ int cnt=0; for(int i=1;i<=n;i++){ if(fabs(p[i].x-x)-p[i].r<-eps){ dl t=sqrt(p[i].r*p[i].r-(x-p[i].x)*(x-p[i].x)); q[++cnt].l=p[i].y-t; q[cnt].r=p[i].y+t; } } sort(q+1,q+cnt+1,cmp1); dl h=-INF,ans=0; for(int i=1;i<=cnt;i++){ if(h<q[i].l)ans+=q[i].r-q[i].l,h=q[i].r; else if(h<q[i].r)ans+=q[i].r-h,h=q[i].r; } return ans; } inline dl simpson(dl l,dl r){ dl mid=(l+r)/2; return (f(l)+4*f(mid)+f(r))*(r-l)/6; } inline dl asr(dl l,dl r,dl ans){ dl mid=(l+r)/2; dl l1=simpson(l,mid),r1=simpson(mid,r); if(fabs(l1+r1-ans)<eps)return l1+r1; return asr(l,mid,l1)+asr(mid,r,r1); } int main(){ n=read(); for(int i=1;i<=n;i++){ p[i].x=read(),p[i].y=read(),p[i].r=read(); } sort(p+1,p+n+1,cmp2); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ int x=p[i].x-p[j].x,y=p[i].y-p[j].y,r=p[j].r-p[i].r; if(x*x+y*y<=r*r){ tag[i]=1;break; } } } int tot=0; for(int i=1;i<=n;i++)if(!tag[i])p[++tot]=p[i]; n=tot; printf("%.3lf\n",asr(-INF,INF,simpson(-INF,INF))); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++