본문 바로가기
PS/코드트리

[그리디] Parametric Search / 폭탄 떨구기

by 행복한라이언 2024. 2. 15.
728x90
반응형

문제링크

https://www.codetree.ai/missions/8/problems/drop-the-bomb?&utm_source=clipboard&utm_medium=text

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

1. 핵심

  • 이분탐색의 대상이 되는 값 → R
    • R로 결정할 수 있는 것은 바로 주어진 범위를 덮는 폭탄의 개수를 결정한다.
    • 덮어야하는 포인트의 첫 시작은 반드시 폭탄의 범위에 들어가야 하므로 이를 폭탄의 시작점으로 생각한다.
  • 폭탄의 범위에 대한 생각
    • (R ~ 폭탄 ~ R) 로 생각할수도 있지만  (폭탄 ~ 2 * R)로 생각할 수 있다. 후자가 다루기 훨씬 편하다.
  • 코드 해설
    • 범위 R에 따른 필요한 폭탄의 수 세는 방법: 폭탄의 범위를 -inf로 초기화를 해놓은 상태에서 각 point들이 폭탄의 범위 들어가 있는지 확인한다. 만약 point의 처음에 설정한 폭탄의 범위보다 크면 새로운 폭탄을 하나 더 설정하여 그 범위를 커버해야한다.
    • 범위R이 커질수록 필요한 폭탄의 수는 감소한다. 우리는 폭탄을 최대 K를 설치할 수 있다.
      • 왜냐하면 K개보다 적게 설치해서 모두 커버된다면 R이 무진장 크다는 것이고 나머지 폭탄은 아무곳에나 설치해도 전부 커버가 되기 때문이다.
      • 그런데 K개 보다 많이 설치하게 되면 폭탄이 터지는 범위 R이 조금 부족하다는 의미가 되므로 R을 키워야한다.
      • 따라서 폭탄의 최대 K개까지 설치하도록 해야한다.
      • R 5(F) 4(F)  || 3(T) 2(T) 1(T) → 이 경우 최대 3개까지 설치할 수 있는 것을 의미하는데 오른쪽이 True이다. 따라서 정답 영역은 오른쪽에 존재한다.

2. 코드(Python)

n, k = map(int, input().split())
points = [int(input()) for _ in range(n)]
points.sort()
inf = int(1e9)
# 좌표위치...10^9..매우 큼! -> 이분탐색
# 이분탐색의 대상: 'R'
# 폭탄의 위치는...?
# 현재 정답 기준 R이 5보다 작으면 F / 5보다 크거나 같으면 T
# (R 폭탄 R) 로 생가하지말고 2R 막대기라고 생각하자!

def get_count(r):
    max_bomb_range = -inf
    
    bomb_cnt = 0
    for point in points:
        if point > max_bomb_range:
            max_bomb_range = point + 2 * r
            bomb_cnt += 1
    return bomb_cnt

# k = 3
# 1 2   3 4 5 .. r
# 5 4 | 2 1 .. bomb_cnt(r)
# F F | T T 
# 폭탄이 최소 k개는 되야함
# k개 보다 폭탄이 적으면 나머지 폭탄은 아무데나 뿌려도 된다.
def binary_search(target):
    l, r = 0, inf
    ans = -1
    while l <= r:
        mid = (l + r) // 2
        if get_count(mid) <= target:
            ans = mid
            r = mid - 1
        else:
            l = mid + 1

    return ans

print(binary_search(k))

 

 

728x90
반응형