求圆面积并

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
//(坐标、半径为-10000..10000)
const int chash=12343;
const double zero=1e-8;
int n,nodes;
double pi;
const int nSIZE=1010;
double x[nSIZE],y[nSIZE],r[nSIZE];
double ans;
double inter[nSIZE][3];
int link[10010],next[10010];
double node[10010][3];
int first[chash];
void initial()
{
    int i;
    pi=asin(1)*2;
    scanf("%d",&n);
    for (i=1; i<=n; i++)
        scanf("%lf %lf %lf",&x[i],&y[i],&r[i]);
    memset(first,0,sizeof(first));
    memset(next,0,sizeof(next));
}
double sqrdist(double x1,double y1,double x2,double y2)
{
    return pow(x1-x2,2)+pow(y1-y2,2);
}
double dist(double x1,double y1,double x2,double y2)
{
    return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
}
void prepare()
{
    int i,j;
    bool b[nSIZE];
    for (i=1; i<=n; i++)
        b[i]=true;
    for (i=1; i<=n; i++)
        for (j=i+1; j<=n; j++)
            if (x[i]==x[j] && y[i]==y[j] && r[i]==r[j])
            {
                b[i]=false;
                break;
            }
    for (i=1; i<=n; i++)
        for (j=1; j<=n; j++)
            if (i!=j && r[i]+zero<r[j])
            {
                if (dist(x[i],y[i],x[j],y[j])<=r[j]-r[i])
                {
                    b[i]=false;
                    break;
                }
            }
    j=0;
    for (i=1; i<=n; i++)
        if (b[i])
        {
            j++;
            x[j]=x[i];
            y[j]=y[i];
            r[j]=r[i];
        }
    n=j;
}
double getangle(double x,double y)
{
    if (x<-zero) return atan(y/x)+pi;
    else if (x>zero)
        if (y>0) return atan(y/x);
        else return atan(y/x)+pi*2;
    else if (y>0) return pi/2 ;
    else return pi*3/2;
}
void getcross(int i,int j,double &t1,double &t2)
{
    double a,b,c,a1,b1,c1,x1,y1,x2,y2,t,l;
    a=(x[i]-x[j])*2;
    b=(y[i]-y[j])*2;
    c=pow(r[j],2)-pow(r[i],2)+pow(x[i],2)-pow(x[j],2)+pow(y[i],2)-pow(y[j],2);
    a1=b;
    b1=-a;
    c1=a1*x[i]+b1*y[i];
    t=a*b1-b*a1;
    x1=(c*b1-b*c1)/t;
    y1=(a*c1-c*a1)/t;
    l=sqrt(pow(r[i],2)-pow(x1-x[i],2)-pow(y1-y[i],2));
    t=sqrt(pow(a1,2)+pow(b1,2));
    x2=x1+l*a1/t;
    y2=y1+l*b1/t;
    x1=x1*2-x2;
    y1=y1*2-y2;
    t1=getangle(x1-x[i],y1-y[i]);
    t2=getangle(x2-x[i],y2-y[i]);
    if (t2<t1) t1=t1-pi*2;
    t=(t1+t2)/2;
    if (dist(x[j],y[j],x[i]+r[i]*cos(t),y[i]+r[i]*sin(t))>r[j])
    {
        t=t1;
        t1=t2;
        t2=t;
        if (t2<zero) t2=t2+pi*2;
        else t1=t1-pi*2;
    }
}
void sort(int l,int r)
{
    int i,j;
    double k1,k2;
    i=l;
    j=r;
    k1=inter[(l+r)>>1][1];
    k2=inter[(l+r)>>1][2];
    while (i<=j)
    {
        while ((inter[i][1]+zero<k1) || (fabs(inter[i][1]-k1)<zero) && (inter[i][2]>k2+zero)) i++;
        while ((inter[j][1]>k1+zero) || (fabs(inter[j][1]-k1)<zero) && (inter[j][2]+zero<k2)) j--;
        if (i<=j)
        {
            inter[0][1]=inter[i][1];
            inter[i][1]=inter[j][1];
            inter[j][1]=inter[0][1];
            inter[0][2]=inter[i][2];
            inter[i][2]=inter[j][2];
            inter[j][2]=inter[0][2];
            i++;
            j--;
        }
    }
    if (l<j) sort(l,j);
    if (i<r) sort(i,r);
}
int getwhere(double x,double y)
{
    int i,t;
    t=((int)(fabs(x+y+zero)*100000))%chash;
    i=first[t];
    while (i!=0)
    {
        if ((fabs(node[i][1]-x)<zero)&&(fabs(node[i][2]-y)<zero))
        {
            return i;
        }
        i=next[i];
    }
    nodes++;
    node[nodes][1]=x;
    node[nodes][2]=y;
    next[nodes]=first[t];
    first[t]=nodes;
    return nodes;
}
double getchord(double r,double a)
{
    return pow(r,2)/2*(a-sin(a));
}
void getnode()
{
    int i,j,k,top,t1,t2;
    nodes=0;
    for (i=1; i<=n; i++)
    {
        top=0;
        for (j=1; j<=n; j++)
            if ((i!=j) && (dist(x[i],y[i],x[j],y[j])+zero<r[i]+r[j]))
            {
                top++;
                getcross(i,j,inter[top][1],inter[top][2]);
            }
        if (top>0)
        {
            sort(1,top);
            k=0;
            for (j=1; j<=top; j++)
                if ((k==0)||(inter[j][1]>inter[k][2]))
                {
                    k++;
                    inter[k][1]=inter[j][1];
                    inter[k][2]=inter[j][2];
                }
                else if (inter[j][2]>inter[k][2]) inter[k][2]=inter[j][2];
            top=k;
            while
            ((top>0)&&(inter[top][2]+zero>inter[1][1]+pi*2))
            {
                if (inter[top][1]-pi*2<inter[1][1])
                    inter[1][1]=inter[top][1]-pi*2;
                top--;
            }
            if (top>0)
            {
                for (j=1; j<=top-1; j++)
                {
                    ans=ans+getchord(r[i],inter[j+1][1]-inter[j][2]);
                    t1=getwhere(x[i]+r[i]*cos(inter[j+1][1]),y[i]+r[i]*sin(inter[j+1][1]));
                    t2=getwhere(x[i]+r[i]*cos(inter[j][2]),y[i]+r[i]*sin(inter[j][2]));
                    link[t1]=t2;
                }
                ans=ans+getchord(r[i],inter[1][1]+pi*2-inter[top][2]);
                t1=getwhere(x[i]+r[i]*cos(inter[1][1]),y[i]+r[i]*sin(inter[1][1]));
                t2=getwhere(x[i]+r[i]*cos(inter[top][2]),y[i]+r[i]*sin(inter[top][2]));
                link[t1]=t2;
            }
        }
        else ans=ans+pi*r[i]*r[i];
    }
}
void work()
{
    int i,j;
    bool visited[10010];
    ans=0;
    getnode();
    memset(visited,0,sizeof (visited));
    for (i=1; i<=nodes; i++)
        if (!visited[i])
        {
            j=i;
            do
            {
                visited[j]=true;
                ans=ans+(node[link[j]][1]*node[j][2]-node[j][1]*node[link[j]][2])/2;
                j=link[j];
            }
            while (j!=i);
        }
    printf("%.6lf\n",ans);
}
int main()
{

    initial();
    prepare();
    work();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值