zoukankan      html  css  js  c++  java
  • 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
    ", ans);
        }
        return 0;
    }

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

    于是后来上网找了几个中学的解析几何公式,终于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
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    使用JDBC连接MySql时出现:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration
    Mysql Lost connection to MySQL server at ‘reading initial communication packet', system error: 0
    mysql-基本命令
    C# 监听值的变化
    DataGrid样式
    C# 获取当前日期时间
    C# 中生成随机数
    递归和迭代
    PHP 时间转几分几秒
    PHP 根据整数ID,生成唯一字符串
  • 原文地址:https://www.cnblogs.com/moonbay/p/4138159.html
Copyright © 2011-2022 走看看