복's

[ 백준 - 8983 ] 사냥꾼 본문

알고리즘/백준

[ 백준 - 8983 ] 사냥꾼

나복이 2023. 12. 25. 01:47
728x90

https://www.acmicpc.net/problem/8983

 

8983번: 사냥꾼

KOI 사냥터에는 N 마리의 동물들이 각각 특정한 위치에 살고 있다. 사냥터에 온 사냥꾼은 일직선 상에 위치한 M 개의 사대(총을 쏘는 장소)에서만 사격이 가능하다. 편의상, 일직선을 x-축이라 가

www.acmicpc.net

처음 풀 때도 참고해서 풀었고, 다시 풀 때도 참고해서 풀었다.

이분 탐색 문제들을 마주하면 가장 안되는게 이분 탐색 알고리즘 자체는 간단한거 같은데, 적재적소에 사용하는게 힘든거 같다.

 

문제 조건만 보면 사대 100,000 x 동물의 수 100,000 이기 때문에 완전 탐색 방식으로는 주어진 시간 제한을 만족할 수 없다는건 알 수 있었다.


[ 📌 풀이 ]

  • 동물과 사대간의 거리를 구하는 공식 |x - a| + b
  • 사대에서 동물을 사냥할 수 없는 조건은 위 공식보다 결과보다 사정거리가 짧은 경우이다.
  • 모든 동물에 대해서 사냥이 가능한지 확인이 필요하다.
  • 사대의 경우 sorting이 되지 않은 상태로 input 이 들어오기 때문에 sorting 해야한다.

[ 사대 이미지 ]

  • 사대의 최대 사거리 이상의 높이에 있는 동물은 어느 사대에서도 잡을 수 없다.

동물이 잡힐 수 있다는 정보만 알게 되면 더 이상 서칭은 진행할 필요 없기 때문에 동물을 타겟으로 잡고 사대 배열을 이분 탐색해서 동물을 잡을 수 있는 사대를 찾은 후 찾게 된다면 다음 동물을 진행하면 된다.


[ 📌 코드 - Python (정글 과정 중 풀이) ]

import sys

M, N, L = map(int, sys.stdin.readline().split())
hunters = list(map(int, sys.stdin.readline().split()))
hunters.sort()
animals = []
count = 0

for _ in range(N):
    x, y = map(int, sys.stdin.readline().split())
    animals.append((x, y))

def binarySearch(x, y):
    global left, right

    while left <= right:
        mid = (left + right) // 2   # 사격 하는 포대 인덱스

        if abs(hunters[mid] - x) + y <= L:
            return True

        if hunters[mid] - x < 0:
            left = mid + 1
        else:
            right = mid - 1

for idx, animal in enumerate(animals):
    left, right = 0, len(hunters) - 1

    if binarySearch(animal[0], animal[1]):
        count += 1

print(count)

[ 📌 코드 - Python ]

"""
# Author    : Lee In Bok 
# Date      : 2023.12.25(Mon)
# Spend Time: 52m 37s
# Runtime   : 42352 KB
# Memory    : 816 ms
# Algoritm  : Binary Search
"""

import sys
inp = sys.stdin.readline

M, N, L = map(int, inp().split())
loc = list(map(int, inp().split()))
loc.sort()
animals = []

cnt = 0

for idx in range(N):
  l, r = 0, len(loc) - 1
  x, y = map(int, inp().split())

  while l <= r:
    mid = (l + r) // 2

    if abs(loc[mid] - x) + y <= L:
      cnt += 1
      break

    if loc[mid] - x > 0:
      r = mid - 1
    else:
      l = mid + 1

print(cnt)

[ 📌 코드 - Java ]

/**
* Author    : Lee In Bok 
* Date      : 2023.12.25(Mon)
* Spend Time: 52m 37s
* Runtime   : 58612 KB
* Memory    : 712 ms
* Algoritm  : Binary Search
 */

package BaekJoon.BinarySearch.Q8983;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Q8983 {
  public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());
    int M = Integer.parseInt(st.nextToken());
    int N = Integer.parseInt(st.nextToken());
    int L = Integer.parseInt(st.nextToken());
    int[] loc = Arrays.stream(br.readLine().split(" "))
                                           .mapToInt(Integer::parseInt)
                                           .sorted()
                                           .toArray();
    int cnt = 0; 

    for(int i = 0; i < N; i++){
      st = new StringTokenizer(br.readLine());
      int x = Integer.parseInt(st.nextToken());
      int y = Integer.parseInt(st.nextToken());
      int l = 0;
      int r = M - 1;

      while(l <= r){
        int mid = (l + r) / 2;
        int gap = loc[mid] - x;

        if(Math.abs(gap) + y <= L){
          cnt++;
          break;
        }

        if(gap > 0){
          r = mid - 1;
        } else {
          l = mid + 1;
        }
      }
    }

    System.out.println(cnt);
  }
}

[ 📌 결과 - Python & Java ]

[ Result - Python & Java ]

728x90

'알고리즘 > 백준' 카테고리의 다른 글

[ 백준 - 1074 ] Z  (1) 2023.12.28
[ 백준 - 2110 ] 공유기 설치  (0) 2023.12.26
[ 백준 - 9020 ] 골드바흐의 추측  (2) 2023.12.24
[ 백준 - 1377 ] 버블 소트  (2) 2023.11.24
[ 백준 - 1676 ] 팩토리얼 0의 개수  (0) 2023.11.15