2021. 9. 5. 21:06ㆍ알고리즘/이진탐색
문제
https://www.acmicpc.net/problem/8983문제 정의
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보다 작거나 같은 양의 정수이다.
출력
출력은 단 한 줄이며, 잡을 수 있는 동물의 수를 음수가 아닌 정수로 출력한다.
예제 입력 1
4 8 4 6 1 4 9 7 2 3 3 4 5 5 1 2 2 1 4 8 4 9 4
예제 출력 1
6
접근 방법
- 주어진 사대의 위치를 오름차순으로 정렬한다.
- 동물의 위치를 하나씩 탐색하며 a + (b - l) <= x <= a - (b - l)에 해당하는 위치에 사대가 있다면 해당 동물은 사냥 가능한 것으로 판단한 뒤 카운트해준다. 단, l > b 인 경우만 해당한다.
- l <= |a-x| + b에 해당하는 동물이 각 사대에서 잡을 수 있는 동물이기에 위와 같은 식으로 바꿀 수 있다.
코드
# https://www.acmicpc.net/problem/8983
# 접근 방법
# 주어진 사대의 위치를 오름차순으로 정렬한다.
# 동물의 위치를 하나씩 탐색하며 a + (b - l) <= x <= a - (b - l)에 해당하는 위치에 사대가 있다면 해당 동물은 사냥 가능한 것으로 판단한 뒤 카운트해준다. 단, l > b 인 경우만 해당한다.
# l <= |a-x| + b에 해당하는 동물이 각 사대에서 잡을 수 있는 동물이기에 위와 같은 식으로 바꿀 수 있다.
import sys
input = sys.stdin.readline
m, n, l = map(int, input().split())
shooting_place = list(map(int, input().split()))
animal = [list(map(int, input().split())) for _ in range(n)]
#m, n, l = 4, 8, 4
#shooting_place = [6, 1, 4, 9]
#animal = [[7, 2], [3, 3], [4, 5], [5, 1], [2, 2], [1, 4], [8, 4], [9, 4]]
shooting_place.sort()
count = 0
for a, b in animal:
if b > l:
continue
start = 0
end = m - 1
while start <= end:
mid = (start+end)//2
if shooting_place[mid] < a + b - l:
start = mid + 1
elif shooting_place[mid] > a - b + l:
end = mid - 1
else:
count += 1
break
print(count)
'알고리즘 > 이진탐색' 카테고리의 다른 글
백준 온라인 저지, 이진탐색 / 11053번: 가장긴증가하는부분수열 (파이썬) (0) | 2021.11.09 |
---|---|
백준 온라인 저지, 이진탐색 / 3649번: 로봇프로젝트 (파이썬 / 백준 골드문제) (0) | 2021.09.15 |
백준 온라인 저지, 이진탐색 / 16434번: 드래곤앤던전 (파이썬 / 백준 골드문제) (0) | 2021.09.05 |
백준 온라인 저지, 이진탐색 / 2343번: 기타레슨 (파이썬) (0) | 2021.09.05 |
백준 온라인 저지, 이진탐색 / 7795번: 먹을 것인가 먹힐 것인가 (파이썬 / 백준 골드문제) (0) | 2021.09.01 |