bjfu1235 两圆公共面积

给定两个圆,求其覆盖的面积,其实也就是求其公共面积(然后用两圆面积和减去此值即得最后结果)。

我一开始是用计算几何的方法做的,结果始终不过。代码如下:

/*

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

const double pi = acos(-1);

typedef struct MyPoint {

    double x, y;

    MyPoint(double xx = 0, double yy = 0) {

        x = xx;

        y = yy;

    }

} MyPoint;



inline double mydistance2(const MyPoint &p1, const MyPoint &p2) {

    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);

}



inline double mydistance(const MyPoint &p1, const MyPoint &p2) {

    return sqrt(mydistance2(p1, p2));

}



MyPoint intersection(MyPoint u1, MyPoint u2, MyPoint v1, MyPoint v2) {

    MyPoint ret = u1;

    double t = ((u1.x - v1.x) * (v1.y - v2.y) - (u1.y - v1.y) * (v1.x - v2.x))

            / ((u1.x - u2.x) * (v1.y - v2.y) - (u1.y - u2.y) * (v1.x - v2.x));

    ret.x += (u2.x - u1.x) * t;

    ret.y += (u2.y - u1.y) * t;

    return ret;

}



void intersection_line_circle(MyPoint c, double r, MyPoint l1, MyPoint l2,

        MyPoint& p1, MyPoint& p2) {

    MyPoint p = c;

    double t;

    p.x += l1.y - l2.y;

    p.y += l2.x - l1.x;

    p = intersection(p, c, l1, l2);

    t = sqrt(r * r - mydistance(p, c) * mydistance(p, c)) / mydistance(l1, l2);

    p1.x = p.x + (l2.x - l1.x) * t;

    p1.y = p.y + (l2.y - l1.y) * t;

    p2.x = p.x - (l2.x - l1.x) * t;

    p2.y = p.y - (l2.y - l1.y) * t;

}



void intersection_circle_circle(MyPoint c1, double r1, MyPoint c2, double r2,

        MyPoint& p1, MyPoint& p2) {

    MyPoint u, v;

    double t;

    t = (1 + (r1 * r1 - r2 * r2) / mydistance(c1, c2) / mydistance(c1, c2)) / 2;

    u.x = c1.x + (c2.x - c1.x) * t;

    u.y = c1.y + (c2.y - c1.y) * t;

    v.x = u.x + c1.y - c2.y;

    v.y = u.y - c1.x + c2.x;

    intersection_line_circle(c1, r1, u, v, p1, p2);

}



int main() {

    freopen("data.in", "r", stdin);

//    freopen("data.out", "w", stdout);

    int T;

    double x, y, r1, r2;

    scanf("%d", &T);

    double ans;

    while (T--) {

        scanf("%lf%lf%lf", &x, &y, &r1);

        MyPoint c1(x, y);

        scanf("%lf%lf%lf", &x, &y, &r2);

        MyPoint c2(x, y);

        double dis2 = mydistance2(c1, c2);

        double dis = sqrt(dis2);

        if (dis >= r1 + r2) { //相离

            ans = pi * r1 * r1 + pi * r2 * r2;

        } else if (dis <= fabs(r1 - r2)) { //包含

            double r = r1 > r2 ? r1 : r2;

            ans = pi * r * r;

        } else { //相交

            MyPoint p1, p2;

            intersection_circle_circle(c1, r1, c2, r2, p1, p2);

            double d2 = mydistance(p1, p2) / 2;

            double angle1 = asin(d2 / r1);

            double angle2 = asin(d2 / r2);

            double Sanjiao1 = sqrt(r1 * r1 - d2 * d2) * d2;

            double Sanjiao2 = sqrt(r2 * r2 - d2 * d2) * d2;

            double San1 = r1 * r1 * angle1;

            double San2 = r2 * r2 * angle2;

            ans = pi * r1 * r1 + pi * r2 * r2;

            ans -= San1 + San2 - Sanjiao1 - Sanjiao2;

        }

        printf("%.6f\n", ans);

    }

    return 0;

}

 

根据后来的调试,应该是对如下图b的情况处理不正确。

bjfu1235 两圆公共面积bjfu1235 两圆公共面积

于是后来上网找了几个中学的解析几何公式,终于a了。

做法是联立两个圆的方程(相减),得到相交弦所在直线方程,然后用点到直接的距离公式得到h1和h2,接着算出θ1和θ2,然后就能求得三角形的面积和扇形的面积了。一开始我以为需要分类讨论上面图a和图b两种情况,后来发现,直接去掉求距离时的取绝对值运算就可以了,因为距离为负的时候,得到的夹角也是负的,这样求的三角形面积是负的,扇形也是原先的相补的那部分,具体的图我就不画了,很容易想明白的。

AC代码如下:

/*

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

const double pi = acos(-1);

typedef struct MyPoint {

    double x, y;

    MyPoint(double xx = 0, double yy = 0) {

        x = xx;

        y = yy;

    }

} MyPoint;



inline double mydistance2(const MyPoint &p1, const MyPoint &p2) {

    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);

}



int main() {

//    freopen("data.in", "r", stdin);

    int T;

    scanf("%d", &T);

    double ans, r1, r2;

    MyPoint c1, c2;

    while (T--) {

        scanf("%lf%lf%lf", &c1.x, &c1.y, &r1);

        scanf("%lf%lf%lf", &c2.x, &c2.y, &r2);

        double dis2 = mydistance2(c1, c2);

        double dis = sqrt(dis2);

        if (dis >= r1 + r2) { //相离

            ans = pi * r1 * r1 + pi * r2 * r2;

        } else if (dis <= fabs(r1 - r2)) { //包含

            double r = r1 > r2 ? r1 : r2;

            ans = pi * r * r;

        } else { //相交

            //h1和h2可能为负

            double h1 = (dis2 + r1 * r1 - r2 * r2) / dis / 2.0;

            double h2 = dis - h1;

            double angle1 = acos(h1 / r1);

            double angle2 = acos(h2 / r2);

            double Sanjiao = sqrt(r1 * r1 - h1 * h1) * dis;

            double Sanxin1 = r1 * r1 * angle1;

            double Sanxin2 = r2 * r2 * angle2;

            ans = pi * r1 * r1 + pi * r2 * r2;

            ans -= Sanxin1 + Sanxin2 - Sanjiao;

        }

        printf("%.6f\n", ans);

    }

    return 0;

}

 

你可能感兴趣的:(B)