Bzoj2178 圆的面积并
Submit: 1720 Solved: 441
Description
给出N个圆,求其面积并
Input
先给一个数字N ,N< = 1000 接下来是N行是圆的圆心,半径,其绝对值均为小于1000的整数
Output
面积并,保留三位小数
正解是计算几何,也可以用simpson积分强行搞。
这里解法是simpson积分
数据炒鸡不友好,精度必须要1e-13才行,于是轻松过SPOJ那道圆面积并的代码被轻松卡掉。
开始尝试各种细节剪枝,比如说删掉所有被大圆包含的小圆,比如说只算有圆的横坐标而跳过空区域,比如说solve的时候多传一个面积参数……
然而还是T得飞起,折腾了一下午,突然发现popoQQQ大神在算f(x)的时候加了个记忆化。http://blog.csdn.net/popoqqq/article/details/42292313
并不会用static,姑且仿照着写了记忆化,成功AC。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 using namespace std; 8 const double eps=1e-13; 9 const int INF=1e9; 10 const int mxn=1010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();} 15 return x*f; 16 } 17 // 18 struct cir{ 19 int x,y,r; 20 friend bool operator < (const cir a,const cir b){return a.r<b.r;} 21 }c[mxn];int cnt=0; 22 inline double dist(cir a,cir b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} 23 //圆 24 struct line{ 25 double l,r; 26 friend bool operator <(const line a,const line b){return a.l<b.l;} 27 }a[mxn],b[mxn];int lct=0; 28 29 30 double f(double x){ 31 static map<double,double>mp; 32 static map<double,double>::iterator it; 33 if((it=mp.find(x))!=mp.end())return it->second; 34 double &re=mp[x]; 35 int i,j; 36 lct=0; 37 for(i=1;i<=cnt;i++){//计算直线截得圆弧长度 38 double dd=c[i].x-x; 39 if(fabs(dd)>=c[i].r)continue; 40 double h= sqrt(c[i].r*c[i].r-dd*dd); 41 a[++lct].l=c[i].y-h; 42 a[lct].r=c[i].y+h; 43 } 44 if(!lct)return re=0.0; 45 double last=-INF; 46 sort(a+1,a+lct+1); 47 for(i=1;i<=lct;i++){//线段长度并 48 if(a[i].l>last){re+=a[i].r-a[i].l;last=a[i].r;} 49 else if(a[i].r>last){re+=a[i].r-last;last=a[i].r;} 50 } 51 // printf("x:%.3f len:%.3f\n",x,len); 52 return re; 53 } 54 inline double sim(double l,double r){ 55 return (f(l)+4*f((l+r)/2)+f(r))*(r-l)/6; 56 } 57 double solve(double l,double r,double S){ 58 double mid=(l+r)/2; 59 double ls=sim(l,mid); 60 double rs=sim(mid,r); 61 if(fabs(rs+ls-S)<eps)return ls+rs; 62 return solve(l,mid,ls)+solve(mid,r,rs); 63 } 64 int n; 65 double ans=0; 66 bool del[mxn]; 67 int main(){ 68 freopen("cir.in","r",stdin); 69 n=read(); 70 int i,j; 71 72 for(i=1;i<=n;i++){ 73 c[i].x=read(); c[i].y=read(); c[i].r=read(); 74 // scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r); 75 } 76 // 77 sort(c+1,c+n+1); 78 for(i=1;i<n;i++) 79 for(j=i+1;j<=n;j++){ 80 if((double)c[j].r-c[i].r>=dist(c[i],c[j])) 81 {del[i]=1;break;} 82 } 83 for(i=1;i<=n;i++) 84 if(!del[i])c[++cnt]=c[i]; 85 //删去被包含的圆 86 double tmp=-INF;int blct=0; 87 for(i=1;i<=cnt;i++){ 88 b[++blct].l=c[i].x-c[i].r; 89 b[blct].r=c[i].x+c[i].r; 90 } 91 sort(b+1,b+blct+1); 92 double L=-INF; 93 for(i=1;i<=blct;i++){ 94 if(b[i].r<=tmp)continue; 95 L=max(tmp,b[i].l); 96 ans+=solve(L,b[i].r,sim(L,b[i].r)); 97 tmp=b[i].r; 98 } 99 printf("%.3f\n",ans); 100 return 0; 101 }
本文为博主原创文章,转载请注明出处。