[python] 백준 8983 :: 사냥꾼 (이분 탐색)
2023. 3. 10. 20:26ㆍAlgorithm
728x90
반응형
[사냥꾼]
# 문제
KOI 사냥터에는 N 마리의 동물들이 각각 특정한 위치에 살고 있다. 사냥터에 온 사냥꾼은 일직선 상에 위치한 M 개의 사대(총을 쏘는 장소)에서만 사격이 가능하다. 편의상, 일직선을 x-축이라 가정하고, 사대의 위치 x1, x2, ..., xM은 x-좌표 값이라고 하자. 각 동물이 사는 위치는 (a1, b1), (a2, b2), ..., (aN, bN)과 같이 x,y-좌표 값으로 표시하자. 동물의 위치를 나타내는 모든 좌표 값은 양의 정수이다.
사냥꾼이 가지고 있는 총의 사정거리가 L이라고 하면, 사냥꾼은 한 사대에서 거리가 L 보다 작거나 같은 위치의 동물들을 잡을 수 있다고 한다. 단, 사대의 위치 xi와 동물의 위치 (aj, bj) 간의 거리는 |xi-aj| + bj로 계산한다.
예를 들어, 아래의 그림과 같은 사냥터를 생각해 보자. (사대는 작은 사각형으로, 동물의 위치는 작은 원으로 표시되어 있다.) 사정거리 L이 4라고 하면, 점선으로 표시된 영역은 왼쪽에서 세 번째 사대에서 사냥이 가능한 영역이다.
사대의 위치와 동물들의 위치가 주어졌을 때, 잡을 수 있는 동물의 수를 출력하는 프로그램을 작성하시오.
# 입력
입력의 첫 줄에는 사대의 수 M (1 ≤ M ≤ 100,000), 동물의 수 N (1 ≤ N ≤ 100,000), 사정거리 L (1 ≤ L ≤ 1,000,000,000)이 빈칸을 사이에 두고 주어진다. 두 번째 줄에는 사대의 위치를 나타내는 M개의 x-좌표 값이 빈칸을 사이에 두고 양의 정수로 주어진다. 이후 N개의 각 줄에는 각 동물의 사는 위치를 나타내는 좌표 값이 x-좌표 값, y-좌표 값의 순서로 빈칸을 사이에 두고 양의 정수로 주어진다. 사대의 위치가 겹치는 경우는 없으며, 동물들의 위치가 겹치는 경우도 없다. 모든 좌표 값은 1,000,000,000보다 작거나 같은 양의 정수이다.
# 출력
출력은 단 한 줄이며, 잡을 수 있는 동물의 수를 음수가 아닌 정수로 출력한다.
풀이
전체 코드
import sys
# 사대의 수 M, 동물의 수 N, 사정거리 L
m, n, l = map(int, input().split())
s = list(map(int, input().split()))
s.sort()
def binary_search(arr, target):
left, right = 0, len(arr)-1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid+1
else:
right = mid - 1
return right
count = 0
for _ in range(n):
x, y = map(int, sys.stdin.readline().split())
# 가장 가까운 사대의 인덱스 찾기
idx = binary_search(s, x)
# 가장 가까운 사대와의 거리, 오른쪽 사대와의 거리 계산하기
dist = abs(x - s[idx]) + y
dist_right = abs(x - s[idx+1]) + y if idx < m-1 else float('inf')
# 가장 가까운 사대와 오른쪽 사대 중에서 최소 거리 구하기
dist = min(dist, dist_right)
# 동물을 잡을 수 있으면 count 증가
if dist <= l:
count += 1
print(count)
1. 각 동물과 가장 가까운 사대를 찾는다.
- 이분 탐색을 시작하기 전에는 항상 정렬 먼저!!
s.sort()
- 동물의 x좌표만 따졌을 때 가장 가까운 사대의 인덱스를 찾는 이분 탐색 함수
def binary_search(arr, target):
left, right = 0, len(arr)-1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid+1
else:
right = mid - 1
return right
- 동물 위치 데이터를 입력 받아서 위에서 만든 함수를 호출해 가장 가까운 사대 인덱스 찾기 ㄱㄱ
for _ in range(n):
x, y = map(int, sys.stdin.readline().split())
# 가장 가까운 사대의 인덱스 찾기
idx = binary_search(s, x)
2. 사대와 동물 간의 거리 구하기
- 1에서 구한 가장 가까운 사대에서 동물 간의 거리를 구한다.
🚨 주의할 점!!
- 찾은 것보다 오른쪽에 있는 사대가 더 가까운 사대일 수도 있다.
🤔 Why?
# 사대의 위치
[1, 2, 3, 10000]
# 동물의 위치
[9000, 0]
이 상태로 이분 탐색을 하면 가장 가까운 사대가 3으로 나온다.
(left와 right가 반전되면 right를 return한다.)
하지만 딱 봐도 동물의 위치는 10000과 더 가깝다!
그러므로 오른쪽 사대에서 더 가갑지는 않은지 확인을 거쳐야 한다.
- 한 칸 오른쪽에 있는 사대와의 거리도 구해서 더 짧은 것으로 바꿔치기 하쟈 🌟
# 가장 가까운 사대와의 거리, 오른쪽 사대와의 거리 계산하기
dist = abs(x - s[idx]) + y
dist_right = abs(x - s[idx+1]) + y if idx < m-1 else float('inf')
# 가장 가까운 사대와 오른쪽 사대 중에서 최소 거리 구하기
dist = min(dist, dist_right)
728x90
반응형
'Algorithm' 카테고리의 다른 글
[python] 백준 2630 :: 색종이 만들기 (분할 정복) (0) | 2023.03.10 |
---|---|
[python] 백준 16564 :: 히오스 프로게이머 (이분 탐색) (0) | 2023.03.10 |
[python] 백준 2470 :: 두 용액 (두 포인터) (0) | 2023.03.10 |