[백준 1358] 하키 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
링크는 가로 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;
}