Educational Codeforces Round 2 D. Area of Two Circles' Intersection
解法
アイデアだけなら大学受験の典型ですね(手計算でとけるかは置いておいて)
2 つの円の半径を r, R (r <= R), 2 つの円の距離を d とします。
- R+r <= d なら, 円は交わらないので答えは 0
- R-r >= d なら, 円 r は 円 R に完全に含まれるので, 答えは pi*r^2
- それ以外の場合は, 辺の長さがそれぞれ R, r, d の三角形が中に出来て, 辺 r に対する角度 phi と, 辺 R に対する角度 theta が, 余弦定理によってわかります。これが分かれば, 交わっている部分の面積は, 2つの「扇型 - 三角形」の形で書けるので, 面積を求められます。
Real add(Real a, Real b) {
if (abs(a+b) < eps * (abs(a)+abs(b))) return 0;
return a+b;
}
bool equal(Real a, Real b) {
return add(a, -b) == 0;
}
struct P {
Real x, y;
P() {}
P(Real x, Real y) : x(x), y(y) {}
P operator+(P p) const {return P(add(x, p.x), add(y, p.y));}
P operator-(P p) const {return P(add(x, -p.x), add(y, -p.y));}
P operator*(Real d) const {return P(x*d, y*d);}
Real dot(P p) const {return add(x*p.x, y*p.y);} // 内積
Real det(P p) const {return add(x*p.y, -y*p.x);} // 外積
Real dist(P p) const {return sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));} // 距離
void normalize() {Real d = sqrt(x*x+y*y); x /= d; y /= d;} // 正規化
bool operator<(const P& rhs) const {
if (x != rhs.x) return x < rhs.x;
return y < rhs.y;
}
bool operator==(const P& rhs) const {
return equal(x, rhs.x) && equal(y, rhs.y);
}
};
const Real pi = acosl(-1);
Real square(Real x) {return x*x;}
Real calc(Real r, Real theta) {
Real ret = r*r*theta;
ret -= 2*(r*sinl(theta)) * (r*cosl(theta)) / 2;
return ret;
}
int main() {
Real x1, y1, R;
Real x2, y2, r;
cin >> x1 >> y1 >> R;
cin >> x2 >> y2 >> r;
P p1(x1, y1), p2(x2, y2);
if (R < r) {
swap(R, r);
swap(p1, p2);
}
Real d = p1.dist(p2);
Real ans;
if (d >= R+r) {
ans = 0;
} else if (R >= d+r) {
ans = r*r*pi;
} else {
Real theta = acosl((R*R+d*d-r*r)/(2*R*d));
Real phi = acosl((r*r+d*d-R*R)/(2*r*d));
ans = calc(R, theta);
ans += calc(r, phi);
}
cout << setprecision(12) << ans << endl;
return 0;
}