bzoj 2178: 圆的面积并

Description

给出N个圆,求其面积并

Input

先给一个数字N ,N< = 1000 接下来是N行是圆的圆心,半径,其绝对值均为小于1000的整数

Output

面积并,保留三位小数

自适应辛普森。。留个模板好了
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps=1e-13;
struct circle
{
     double x,y;
     double r;
};
circle a[1001],cir[1001];
struct loc
{
	 double rd;
	 double x,y;
     double l,r;
}sx[1001];
struct line
{
     double l,r;
}px[1001];
int p;
int st,se;
inline bool cmp1(circle x,circle y)
{
     if(x.r<y.r)
          return true;
     return false;
}
inline bool cmp2(circle x,circle y)
{
     if(x.x-x.r<y.x-y.r)
          return true;
     return false;
}
inline bool cmp3(line x,line y)
{
	 if(x.l<y.l)
	      return true;
     return false;
}
inline double fabs(double x)
{
     if(x<0)
          x=-x;
     return x;
}
inline double dist(int i,int j)
{
     return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
inline double geth(double x)
{
     int pp=0;
     int i,j;
     double len=0,dis;
     for(i=st;i<=se;i++)
     {
          if(sx[i].l>=x||sx[i].r<=x)
               continue;
          dis=sqrt(sx[i].rd*sx[i].rd-(x-sx[i].x)*(x-sx[i].x));
          pp++;
          px[pp].l=sx[i].y-dis;
          px[pp].r=sx[i].y+dis;
     }
     sort(px+1,px+1+pp,cmp3);
     double r;
     for(i=1;i<=pp;i++)
     {
          r=px[i].r;
          for(j=i+1;j<=pp;j++)
          {
               if(px[j].l>r)
                    break;
               if(px[j].r>r)
                    r=px[j].r;
          }
          len+=r-px[i].l;
          i=j-1;
     }
     return len;
}
inline double cal(double len,double lh,double mh,double rh)
{
     return (lh+mh*(double)4+rh)*len/(double)6;
}
inline double simpson(double l,double mid,double r,double lh,double mh,double rh,double s)
{
     double mid1,mid2;
     mid1=(l+mid)/(double)2;
     mid2=(mid+r)/(double)2;
     double mh1=geth(mid1),mh2=geth(mid2);
     double s1=cal(mid-l,lh,mh1,mh),s2=cal(r-mid,mh,mh2,rh);
     if(fabs(s1+s2-s)<eps)
          return s1+s2;
     return simpson(l,mid1,mid,lh,mh1,mh,s1)+simpson(mid,mid2,r,mh,mh2,rh,s2);
}
bool flag[1001];
int main()
{
     int n;
     scanf("%d",&n);
     memset(flag,false,sizeof(flag));
     int i,j;
     for(i=1;i<=n;i++)
          scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
     sort(a+1,a+1+n,cmp1);
     for(i=1;i<=n;i++)
     {
          for(j=i+1;j<=n;j++)
          {
               if(dist(i,j)<a[j].r-a[i].r)
               {
                    flag[i]=true;
                    break;
               }
          }
     }
     for(i=1;i<=n;i++)
     {
          if(!flag[i])
          {
               p++;
               cir[p]=a[i];
          }
     }
     sort(cir+1,cir+1+p,cmp2);
     for(i=1;i<=p;i++)
     {
     	  sx[i].x=cir[i].x;
     	  sx[i].y=cir[i].y;
     	  sx[i].rd=cir[i].r;
          sx[i].l=cir[i].x-cir[i].r;
          sx[i].r=cir[i].x+cir[i].r;
     }
     double l,r,mid,lh,rh,mh;
     double ans=0;
     for(i=1;i<=p;i++)
     {
          l=sx[i].l;
		  r=sx[i].r;
          for(j=i+1;j<=p;j++)
          {
               if(sx[j].l>r)
                    break;
               if(sx[j].r>r)
                    r=sx[j].r;
          }
          st=i;
          se=j-1;
          i=j-1;
          mid=(l+r)/(double)2;
          lh=geth(l);
          rh=geth(r);
          mh=geth(mid);
          ans+=simpson(l,mid,r,lh,mh,rh,cal(r-l,lh,mh,rh));
	 }
	 printf("%.3lf\n",ans);
     return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值