Intersection HDU-5120 计算几何+容斥定理

本文详细解析了一个涉及四个圆的几何问题,通过计算圆a与圆b的交集面积减去与其他圆的交集,展示了如何利用S总 = S(aR∩bR) - S(aR∩br) - S(ar∩bR) + S(ar∩br)的公式来求解。代码实例展示了如何在C++中实现这一计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Intersection

在这里插入图片描述

solution

相 当 于 四 个 圆 : a R , a r , b R , b r 相当于四个圆:aR,ar,bR,br aR,ar,bR,br

S 总 = S ( a R ) ∩ S ( b R ) − S ( a R ) ∩ S ( b r ) − S ( a r ) ∩ S ( b R ) + S ( a r ) ∩ S ( b r ) S_总=S(aR)∩S(bR)-S(aR)∩S(br)-S(ar)∩S(bR)+S(ar)∩S(br) S=S(aR)S(bR)S(aR)S(br)S(ar)S(bR)+S(ar)S(br)

code

/*SiberianSquirrel*//*CuteKiloFish*/
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
const ll MOD = ll(998244353);
const ll INF = ll(1e18 + 10);
const double eps = 1e-8;
const double pi = acos(-1.0);
const int N = int(1e5 + 10);
const int M = int(1e3 + 10);
inline int rnd(){static int seed=2333;return seed=(((seed*666666ll+20050818)%998244353)^1000000007)%1004535809;}
template <class T> void read(T &x) {
    static char ch;static bool neg;
    for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
    for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
    x=neg?-x:x;
}
ll add(ll a, ll b) {return (a + b) % MOD;}
ll sub(ll a, ll b) {return (a - b + MOD) % MOD;}
ll mul(ll a, ll b) {a %= MOD; b %= MOD;return a * b % MOD;}
//VAR
int sgn(double x) {
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
inline double sqr(double x) {
    return x*x;
}
struct Point {
    double x,y;
    Point() {}
    Point(double _x,double _y) {
        x = _x;
        y = _y;
    }
    void input() {
        cin >> x >> y;
    }
    bool operator == (Point b)const {
        return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
    }
    bool operator < (Point b)const {
        return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
    }
    Point operator -(const Point &b)const {
        return Point(x-b.x,y-b.y);
    }
    double operator ^(const Point &b)const {
        return x*b.y - y*b.x;
    }
    double operator *(const Point &b)const {
        return x*b.x + y*b.y;
    }
    double distance(Point p) {
        return hypot(x-p.x,y-p.y);
    }
    Point operator +(const Point &b)const {
        return Point(x+b.x,y+b.y);
    }
    Point operator *(const double &k)const {
        return Point(x*k,y*k);
    }
    Point operator /(const double &k)const {
        return Point(x/k,y/k);
    }
};
struct circle {
    Point p;
    double r;
    circle() {}
    bool operator == (circle v) {
        return (p==v.p) && sgn(r-v.r)==0;
    }
    bool operator < (circle v)const {
        return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
    }
    double area() {
        return pi*r*r;
    }
    int relationcircle(circle v) {
        double d = p.distance(v.p);
        if(sgn(d-r-v.r) > 0)return 5;
        if(sgn(d-r-v.r) == 0)return 4;
        double l = fabs(r-v.r);
        if(sgn(d-r-v.r)<0 && sgn(d-l)>0)return 3;
        if(sgn(d-l)==0)return 2;
        if(sgn(d-l)<0)return 1;
    }
    double areacircle(circle v) {
        int rel = relationcircle(v);
        if(rel >= 4)return 0.0;
        if(rel <= 2)return min(area(),v.area());
        double d = p.distance(v.p);
        double hf = (r+v.r+d)/2.0;
        double ss = 2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
        double a1 = acos((r*r+d*d-v.r*v.r)/(2.0*r*d));
        a1 = a1*r*r;
        double a2 = acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d));
        a2 = a2*v.r*v.r;
        return a1+a2-ss;
    }
};
// FUNCTION
//WORK
void solve(int cases = 0) {
    int o; cin >> o; while(o --) {
        double r, R; cin >> r >> R;
        Point p1, p2; p1.input(); p2.input();
        circle ar, aR, br, bR;
        ar.p = p1; br.p = p2;
        aR.p = p1; bR.p = p2;
        ar.r = r; br.r = r;
        aR.r = R; bR.r = R;
        cout << "Case #" << ++ cases << ": " << fixed << setprecision(6) << aR.areacircle(bR) - aR.areacircle(br) - bR.areacircle(ar) + ar.areacircle(br) << endl;
    }
}
//MAIN
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifdef ACM_LOCAL
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
    signed test_index_for_debug = 1;
    char acm_local_for_debug = 0;
    do {
        if (acm_local_for_debug == '$') exit(0);
        if (test_index_for_debug > 20)
            throw runtime_error("Check the stdin!!!");
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    } while (cin >> acm_local_for_debug && cin.putback(acm_local_for_debug));
#else
    solve();
#endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值