题目的意思是给你一个大圆一个小圆,这两个圆组成一个环,然后有两个环处在不同的坐标位置,求这两个环相交的面积。

相交面积=S大环∩大环-S大环∩小环*2+S小环∩小环,如下图所示:

blob.png

那么两个环之间相交的面积怎么求呢?

blob.png

如上图,

两个圆相交的面积=S扇形OrAB-S三角形OrAB+S扇形ORAB-S三角形ORAB

扇形面积怎么求?

我们知道两个圆心之间的距离是可以求出来的,R、r都知道,三边都知道那么用余弦定理可以求出

cos∠AOrOR= (r*r+d*d-R*R)/(2*r*d)

所以∠AOrB=2*acos(cos∠AOrOR)

然后用扇形面积公式可以求出S扇形OrAB,另一个圆同理。

S三角形OrAB+S三角形ORAB=S四边形AOrBOR=S三角形OrAOR*2

S三角形OrAOR*2=d*h/2

h怎么求?我们知道了cos∠AOrOR,那么只要用r*sin∠AOrOR即可。


代码:

StatusAccepted
Time374ms
Memory1596kB
Length1000
LangG++
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double pi=3.141592654;
struct Circle{
    double x, y, r;
}cs1, cs2, cb1, cb2;
int t, r, R, x, y, x2, y2;
double cArea(Circle c1, Circle c2){
    double d=sqrt((c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y));    //求距离
    if(c1.r+c2.r<=d)return 0;                                           //相离的情况
    double minr=min(c1.r, c2.r), maxr=max(c1.r, c2.r);
    if(maxr-minr>=d)return pi*minr*minr;                                //包含的情况
    double ang1=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));            //两个小角度
    double ang2=acos((c2.r*c2.r+d*d-c1.r*c1.r)/(2*c2.r*d));
    return c1.r*c1.r*ang1+c2.r*c2.r*ang2-c1.r*sin(ang1)*d;            //相交的情况
}
int main()
{
    scanf("%d", &t);
    for(int cas=1;cas<=t;cas++){
        scanf("%d%d%d%d%d%d", &r,&R,&x,&y,&x2,&y2);
        cs1.r=cs2.r=r;
        cb1.r=cb2.r=R;
        cs1.x=cb1.x=x;
        cs1.y=cb1.y=y;
        cs2.x=cb2.x=x2;
        cs2.y=cb2.y=y2;
        double ans=cArea(cb1, cb2)-2*cArea(cb1, cs2)+cArea(cs1, cs2);
        printf("Case #%d: %.6lf\n", cas, ans);
    }
    return 0;
}