작성일 :

문제 링크

1358번 - 하키

설명

링크는 가로 W, 세로 H의 직사각형과 양쪽 끝의 반원을 합친 형태입니다. 반원의 반지름은 H를 2로 나눈 값입니다.

직사각형의 왼쪽 아래 모서리는 (X, Y)이고, 왼쪽 원의 중심은 (X, Y + H/2), 오른쪽 원의 중심은 (X + W, Y + H/2)입니다.

선수 좌표가 직사각형 안이거나 두 원 중 하나 안에 있는지 판정해 개수를 세는 문제입니다.


접근법

먼저, 점이 원 안에 있는지 판정하려면 중심까지의 거리가 반지름 이하인지 확인해야 합니다. 거리를 직접 구하면 제곱근 계산이 필요하지만, 양변을 제곱하면 제곱거리와 반지름 제곱을 비교하는 것으로 대체할 수 있습니다. 따라서 반지름의 제곱을 미리 계산해둡니다.

다음으로, 각 선수에 대해 세 영역을 확인합니다. 직사각형 안에 있는지는 x, y 좌표가 각각 범위 안에 있는지로 판정합니다. 원 안에 있는지는 중심까지의 제곱거리가 반지름 제곱 이하인지로 판정합니다.

세 영역 중 하나라도 해당하면 개수를 증가시킵니다.



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
33
34
35
36
37
using System;

namespace Solution {
  class Program {
    static void Main(string[] args) {
      var first = Console.ReadLine()!.Split();
      var W = int.Parse(first[0]);
      var H = int.Parse(first[1]);
      var X = int.Parse(first[2]);
      var Y = int.Parse(first[3]);
      var P = int.Parse(first[4]);

      var r = H / 2;
      var r2 = r * r;
      var cx1 = X;
      var cy1 = Y + r;
      var cx2 = X + W;
      var cy2 = Y + r;

      var ans = 0;
      for (var i = 0; i < P; i++) {
        var p = Console.ReadLine()!.Split();
        var px = int.Parse(p[0]);
        var py = int.Parse(p[1]);

        var inRect = (px >= X && px <= X + W && py >= Y && py <= Y + H);
        var inCircle1 = ((px - cx1) * (px - cx1) + (py - cy1) * (py - cy1) <= r2);
        var inCircle2 = ((px - cx2) * (px - cx2) + (py - cy2) * (py - cy2) <= r2);

        if (inRect || inCircle1 || inCircle2)
          ans++;
      }

      Console.WriteLine(ans);
    }
  }
}

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
#include <bits/stdc++.h>
using namespace std;

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

  int W, H, X, Y, P; cin >> W >> H >> X >> Y >> P;

  int r = H / 2;
  int r2 = r * r;
  int cx1 = X, cy1 = Y + r;
  int cx2 = X + W, cy2 = Y + r;

  int ans = 0;
  for (int i = 0; i < P; i++) {
    int px, py; cin >> px >> py;
    bool inRect = (px >= X && px <= X + W && py >= Y && py <= Y + H);
    bool inCircle1 = (px - cx1) * (px - cx1) + (py - cy1) * (py - cy1) <= r2;
    bool inCircle2 = (px - cx2) * (px - cx2) + (py - cy2) * (py - cy2) <= r2;
    if (inRect || inCircle1 || inCircle2)
      ans++;
  }

  cout << ans << "\n";

  return 0;
}