[Python] 백준 8983 사냥꾼 (Binary Search)
📌 문제
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 | 9 | M ≤ 10, N ≤ 10, X ≤ 10 |
2 | 14 | M ≤ 20, N ≤ 20, X ≤ 20 |
3 | 18 | M ≤ 100, N ≤ 100 |
4 | 19 | M ≤ 2,000, N ≤ 2,000 |
5 | 40 | 추가적인 제약 조건은 없다. |
예제 입력 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
예제 입력 2
1 5 3
3
2 2
1 1
5 1
4 2
3 3
예제 출력 2
5
📌 풀이
💬 Code
import sys
from bisect import bisect_left
input = sys.stdin.readline
m, n, l = map(int, input().split())
shoot = list(map(int, input().split()))
shoot.sort()
cnt = 0
for _ in range(n):
x, y = map(int, input().split())
if y <= l:
idx = bisect_left(shoot, x)
for k in [idx-1, idx, idx+1]:
if k < 0 or k >= m:
continue
if abs(shoot[k] - x) + y <= l:
cnt += 1
break
print(cnt)
💡 Solution
처음엔 그냥 단순히 2중포문으로 풀었는데 서브태스크 5번을 통과하지 못하고 100점 만점에 60점만 얻을 수 있었다 ^_ㅠ 쩝....... 아직 이분탐색이 익숙지 않은 ㄴr..☆★ 어떤 상황에서 써야 할지 감이 안 잡힘 ㅠ 이분탐색 문제 몇개 더 풀어봐야겠다.
아무튼 성공코드를 뜯어보자.
- shoot: 사대의 x좌표를 담은 리스트 (오름차순 정렬된 상태)
- x, y, m, l: 동물의 x좌표, 동물의 y좌표, 사대 개수, 사정거리
- idx: 이번 동물로부터 가장 가까운 사대의 인덱스
일단 x, y를 입력받고 y가 사정거리(l)보다 큰 경우에는 절대 맞출 수 없으므로 y <= l로 조건을 걸어준다.
이 동물을 사격할 수 있는가를 동물과 가까운 사대에서만 탐색하기 위해 이분탐색을 이용한다. shoot에 x가 들어가려면 몇번째 인덱스에 들어갈지를 bisect_left를 통해 구하고, 해당 인덱스의 전후 인덱스까지 살핌으로써 동물과 가까이 위치한 사대들을 탐색한다. 해당 사대들에서 거리계산을 수행하고 맞출 수 있으면 카운트를 올려준 후 for문을 빠져나온다.
Author And Source
이 문제에 관하여([Python] 백준 8983 사냥꾼 (Binary Search)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hygge/Python-백준-8983-사냥꾼-Binary-Search저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)