【AtCoder】ABC 460 B - Two Rings

B - Two Ringsatcoder.jp favicon

実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 128 / NoviSteps: 4Q / 配点: 250

問題概要

xyxy 平面上に 22 つの円 C1,C2C_1, C_2 がある。 円 C1C_1 は中心の座標が (X1,Y1)(X_1, Y_1) で半径が R1R_1 、円 C2C_2 は中心の座標が (X2,Y2)(X_2, Y_2) で半径が R2R_2 である。

C1C_1 と円 C2C_2 が共有点を持つかどうかを判定せよ。 なお、 TT 個のテストケースが与えられるのでそれぞれについて答えを求めること。

制約

  • 1T1001 \leq T \leq 100
  • 0X1,Y1,X2,Y21090 \leq X_1, Y_1, X_2, Y_2 \leq 10^9
  • 1R1,R21091 \leq R_1, R_2 \leq 10^9
  • 入力される値は全て整数

考察

C1C_1C2C_2 の中心間距離を dd とすれば、2円が共有点を持つための必要十分条件は

R1R2dR1+R2|R_1 - R_2| \leq d \leq R_1 + R_2

である。

しかし、このままだと dd は小数になり、大小比較時に誤差が発生する可能性があるため、各項が正であることを利用して両辺を二乗する。

(R1R2)2d2(R1+R2)2(R_1 - R_2)^2 \leq d^2 \leq (R_1 + R_2)^2

したがって、この条件を満たすかどうかをテストケースごとに判定すればよい。

実装例

CPP
1.#include <bits/stdc++.h>
2.using namespace std;
3.
4.using ll = long long;
5.
6.// ======================================== //
7.
8.bool solve()
9.{
10. ll X1, Y1, R1, X2, Y2, R2;
11. cin >> X1 >> Y1 >> R1 >> X2 >> Y2 >> R2;
12.
13. ll d2 = (X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2);
14. ll diff2 = (R1 - R2) * (R1 - R2);
15. ll sum2 = (R1 + R2) * (R1 + R2);
16.
17. if (diff2 <= d2 && d2 <= sum2)
18. return true;
19. else
20. return false;
21.}
22.
23.int main()
24.{
25. int T;
26. cin >> T;
27.
28. while (T--)
29. {
30. cout << (solve() ? "Yes" : "No") << endl;
31. }
32.
33. return 0;
34.}
Submission #76417542 - AtCoder Beginner Contest 460atcoder.jp favicon

実装時間: 5 分以内

コメント

参考:

2つの円の位置関係 | 高校数学の美しい物語manabitimes.jp favicon