hdu 5120 题解 Intersection

求两个圆环的交,感觉没有做错啊,结果c++一直wa,改了G++以后就过了,实在想不通

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
int sig(double x){return (x>eps)-(x<-eps);}
struct P
{
    double x,y;
    P(double a=0,double b=0):x(a),y(b){}
    P operator +(const P &a)const{
        return P(x+a.x,y+a.y);
    }
    P operator -(const P &a)const{
        return P(x-a.x,y-a.y);
    }
    P operator *(const double a)const{
        return P(x*a,y*a);
    }
    P operator /(const double a)const{
        return P(x/a,y/a);
    }
    double operator *(const P &a)const{
        return x*a.x+y*a.y;
    }
    double operator ^(const P &a)const{
        return x*a.y-y*a.x;
    }
    int operator ==(const P& a)const{
        return sig(x-a.x)==0&&sig(y-a.y)==0;
    }
};
double dis(P a,P b)
{
    return sqrt((b-a)*(b-a));
}
P rotat(const P &p,double cost,double sint)
{
    double x=p.x,y=p.y;
    return P(x*cost-y*sint,x*sint+y*cost);
}
struct Circle
{
    P o;double r;
    Circle(){};
    Circle(P o1,double r1):o(o1),r(r1){}
    int cp_ccl(Circle c,P *p)
    {
        double d=dis(o,c.o);
        if(sig(d+min(r,c.r)-max(r,c.r))<=0||sig(d)==0) return 0;
        double cost=(r*r+d*d-c.r*c.r)/(2*r*d);
        double sint=sqrt(1-cost*cost);
        P v=(c.o-o)/d*r;
        p[0]=o+rotat(v,cost,-sint),p[1]=o+rotat(v,cost,sint);
        if(p[0]==p[1]) return 1;
        return 2;
    }
};
//容斥求交
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        double r,R;
        scanf("%lf%lf",&r,&R);
        P o1,o2;
        scanf("%lf%lf%lf%lf",&o1.x,&o1.y,&o2.x,&o2.y);
        Circle R1,R2,r1,r2;
        R1=Circle(o1,R);R2=Circle(o2,R);
        r1=Circle(o1,r);r2=Circle(o2,r);
        double sum=0,sum1=pi*(R*R-r*r);
        int flag=0;
        P p[4];
        int tt=R1.cp_ccl(R2,p); //两大圆求交
        if(tt==2)
        {
            double ang=2*asin(dis(p[0],p[1])/2/R);
            double s1=ang*R*R/2-fabs((p[0]-o1)^(p[1]-o1))/2;
            sum+=(2*s1);
            flag=1;
        }
        tt=r1.cp_ccl(r2,p); //两小圆求交
        if(tt==2)
        {
            double ang=2*asin(dis(p[0],p[1])/2/r);
            double s1=ang*r*r/2-fabs((p[0]-o1)^(p[1]-o1))/2;
            sum+=(s1*2);
            flag=1;
        }
        tt=R1.cp_ccl(r2,p);//大圆与小圆求交
        if(tt==2)
        {
            P pm=(p[0]+p[1])/2;
            if(sig(dis(o1,o2)-dis(o1,pm))<0)
            {
                double ang=2*asin(dis(p[0],p[1])/2/R);
                double s1=ang*R*R/2-fabs((p[0]-o1)^(p[1]-o1))/2;
                ang=2*asin(dis(p[0],p[1])/2/r);
                double s2=(2*pi-ang)*r*r/2+fabs((p[0]-o2)^(p[1]-o2))/2;
                sum-=((s1+s2)*2);
            }
            else
            {
                double ang=2*asin(dis(p[0],p[1])/2/R);
                double s1=ang*R*R/2-fabs((p[0]-o1)^(p[1]-o1))/2;
                ang=2*asin(dis(p[0],p[1])/2/r);
                double s2=ang*r*r/2-fabs((p[0]-o2)^(p[1]-o2))/2;
                sum-=((s1+s2)*2);
            }
            flag=1;
        }
        else
        {
            if(sig(dis(r2.o,R1.o)-R)<=0)
                sum-=(2*pi*r*r);
        }
        if(flag==0)
        {
            if(o1==o2)
                printf("Case #%d: %.6f\n",i,sum1);
            else
                printf("Case #%d: 0.000000\n",i);
        }
        else
            printf("Case #%d: %.6f\n",i,sum);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值