작성일 :

문제 링크

7869번 - 두 원

설명

두 원의 중심 좌표와 반지름이 주어질 때, 두 원이 겹치는 부분의 넓이를 구하는 문제입니다.


접근법

두 원의 중심 사이 거리에 따라 세 가지 경우로 나뉩니다.

먼저, 두 원이 완전히 분리된 경우입니다. 중심 거리가 두 반지름의 합 이상이면 겹치는 부분이 없으므로 넓이는 0입니다.

다음으로, 한 원이 다른 원에 완전히 포함된 경우입니다. 중심 거리에 작은 반지름을 더한 값이 큰 반지름 이하이면, 작은 원 전체가 큰 원 안에 들어갑니다. 이때 겹치는 넓이는 작은 원의 넓이입니다.

마지막으로, 두 원이 부분적으로 겹치는 경우입니다. 코사인 법칙으로 각 원에서 교차 부분이 차지하는 각도를 구합니다. 각 원에서 부채꼴 넓이를 구한 뒤, 겹치는 삼각형 부분을 빼면 렌즈 모양의 교차 넓이가 됩니다.



Code

C#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;

class Program {
  static void Main() {
    var s = Console.ReadLine()!.Split();
    var x1 = double.Parse(s[0]);
    var y1 = double.Parse(s[1]);
    var r1 = double.Parse(s[2]);
    var x2 = double.Parse(s[3]);
    var y2 = double.Parse(s[4]);
    var r2 = double.Parse(s[5]);

    if (r1 < r2) { (r1, r2) = (r2, r1); (x1, x2) = (x2, x1); (y1, y2) = (y2, y1); }

    var dx = x1 - x2;
    var dy = y1 - y2;
    var d = Math.Sqrt(dx * dx + dy * dy);
    var area = 0.0;

    if (d >= r1 + r2) area = 0.0;
    else if (d + r2 <= r1) area = Math.PI * r2 * r2;
    else {
      var t1 = Math.Acos((d * d + r1 * r1 - r2 * r2) / (2 * d * r1));
      var t2 = Math.Acos((d * d + r2 * r2 - r1 * r1) / (2 * d * r2));
      var lens = r1 * r1 * t1 + r2 * r2 * t2;
      var tri = 0.5 * Math.Sqrt(Math.Max(0.0, (-d + r1 + r2) * (d + r1 - r2) * (d - r1 + r2) * (d + r1 + r2)));
      area = lens - tri;
    }

    Console.WriteLine(area.ToString("0.000"));
  }
}

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>
using namespace std;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  double x1, y1, r1, x2, y2, r2;
  cin >> x1 >> y1 >> r1 >> x2 >> y2 >> r2;
  if (r1 < r2) { swap(r1, r2); swap(x1, x2); swap(y1, y2); }

  double dx = x1 - x2, dy = y1 - y2;
  double d = sqrt(dx*dx + dy*dy);
  double area;

  if (d >= r1 + r2) area = 0.0;
  else if (d + r2 <= r1) area = M_PI * r2 * r2;
  else {
    double t1 = acos((d*d + r1*r1 - r2*r2) / (2 * d * r1));
    double t2 = acos((d*d + r2*r2 - r1*r1) / (2 * d * r2));
    double lens = r1*r1 * t1 + r2*r2 * t2;
    double tri = 0.5 * sqrt(max(0.0, (-d + r1 + r2) * (d + r1 - r2) * (d - r1 + r2) * (d + r1 + r2)));
    area = lens - tri;
  }

  cout.setf(ios::fixed);
  cout.precision(3);
  cout << area << "\n";

  return 0;
}