hdu 5120 Intersection 2014ACM/ICPC亚洲区北京站-重现赛

画个图就可以用容斥原理推出公式。

area=circle1大圆和circle2大圆面积交-circle1大圆和circle2小圆面积交-circle1小圆和circle2大圆面积交+circle1小圆和circle2小圆面积交

然后看一下圆心重合、相切、分离的几种case能否满足即可,这里的模板比之前的多加了个两个圆重合的特判。

另外在求圆心距的时候,要注意圆心重合时要特判return 0,如果用sqrt会返回nan(虽然开始没理这个也A了==)。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<ctype.h>
#include<map>
#include<time.h>
#include<bitset>
using namespace std;
//hdu 5120

int T;
double r;
double R;
double x[2];
double y[2];
double ans;
const double eps=1e-9;
class circle
{
public:
    double x;
    double y;
    double r;
    circle(){x=0;y=0;r=0;}
    circle(double xx,double yy,double rr)
    {
        x=xx;
        y=yy;
        r=rr;
    }
};
circle cir[25];
double pi=acos(-1.0);
double dis(circle r1,circle r2)
{
    double xd=r1.x-r2.x;
    double yd=r1.y-r2.y;
    //cout<<"dis "<<xd<<" "<<yd<<endl;
    if(abs(xd)<eps&&abs(yd)<eps) return 0;
    else return sqrt(xd*xd+yd*yd);
}
double intersection(circle c1,circle c2)
{
    double d=dis(c1,c2);
    //cout<<"d: "<<d<<endl;
    if(d<eps) return min(pi*c1.r*c1.r,pi*c2.r*c2.r);//特判两个圆重合的case
    else if(d>=(c1.r+c2.r)) return 0;
    else if(d<fabs(c1.r-c2.r))
    {
       // cout<<"haha  "<<d<<" "<<fabs(c1.r-c2.r)<<endl;
        //cout<<"area: "<<pi*c1.r*c1.r<<" "<<pi*c2.r*c2.r<<endl;
        return min(pi*c1.r*c1.r,pi*c2.r*c2.r);
    }
    else
    {
        double h=(c1.r+c2.r+d)/2.0;
        double s=sqrt(h*(h-c1.r)*(h-c2.r)*(h-d))*2.0;//三角形面积的海伦公式
        double angle1=acos((c1.r*c1.r+d*d-c2.r*c2.r)/2.0/c1.r/d);//余弦定理
        double angle2=acos((c2.r*c2.r+d*d-c1.r*c1.r)/2.0/c2.r/d);
        double s1=angle1*c1.r*c1.r;
        double s2=angle2*c2.r*c2.r;//求扇形面积
        return s1+s2-s;//inclusive and declusive principle
    }
}
int main()
{
    freopen("input.txt","r",stdin);
    //freopen("data.txt","r",stdin);
    //freopen("out1.txt","w",stdout);
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%lf %lf",&r,&R);
        scanf("%lf %lf",&x[0],&y[0]);
        scanf("%lf %lf",&x[1],&y[1]);
        ans=0;
        circle c1=circle(x[0],y[0],r);
        circle c2=circle(x[0],y[0],R);
        circle c3=circle(x[1],y[1],r);
        circle c4=circle(x[1],y[1],R);
        //cout<<"inter: "<<intersection(c2,c4)<<" "<<intersection(c1,c4)<<" "<<intersection(c2,c3)<<" "<<intersection(c1,c3)<<endl;
        ans=intersection(c2,c4)-intersection(c1,c4)-intersection(c2,c3)+intersection(c1,c3);
        printf("Case #%d: %.6lf\n",ca,ans);
    }
     return 0;
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值