<aside> 🔥 백준 2805번 링크

</aside>

<aside> 🔥 문제 정리

첫째줄에 나무의 수 n이 주어지고, 필요한 나무의 길이 m이 주어진다.

둘째줄에 n개의 나무의 길이가 주어진다.

절단기에 높이 h를 지정해야하는데 둘째줄에 주어진 나무의 한줄을 연속해서 잘라낸다.

여기서 절단기의 높이만큼 자른 나무만 가져갈 수 있는데 이 길이가 m인 경우의 최대 수를 구하라.

</aside>

<aside> 🔥 문제가 처음에 이해하기가 어렵다.

아래 그림과 같이 목재의 길이가 20 15 10 17 인 경우에 7의 나무를 얻고자하면

15로 잘라내야한다는 것이다.

Untitled

</aside>

<aside> 🔥 접근 방법

목재절단기의 높이를 0 ~ 나무이 길이의 최대 로 지정한다.

이진 탐색으로 중간 지점을 목재절단기의 높이로 두고 잘라냈을 때 얻은 나무의 길이가 목표치보다 크면,

중간 지점을 높혀서 나무가 덜 자르게 한다.

반대로 얻은 나무의 길이가 목표치보다 작다면 중간지점을 낮춰서 나무가 더 많이 잘리게 한다.

</aside>

<aside> 🔥 코드 진행

(1) 입력값을 받아오고 low, high를 지정한다.

low는 0부터 high는 현재 나무들의 길이중 최대로 지정한다.

import sys

def input():
    return sys.stdin.readline().strip()

n, m = map(int, input().split())
li = list(map(int, input().split()))

lo = 0          # 0 부터
hi = max(li)    # 리스트에서 가장 큰값
result = 0      # 결과값

(2) low가 high보다 높아지지 않는 선에서 반복문을 실행한다.

모든 나무의 길이가 들어있는 리스트를 순회하며 중간값으로 자르고 얻은 나무의 길이를

total에 저장한다.

while lo <= hi:
    total = 0               # 나무 자른 총 양
    mid = (lo + hi) // 2    # 중간 값

    # 리스트를 순회한다.
    for x in li:
        # 중간값으로 잘랐을때 잘려나간 나무들
        if x > mid:
            # 총 양에 잘려나간 길이 넣기
            total += x - mid

(3) 위에서 얻은 total의 양과 목표치를 비교해준다.

목표치보다 적게 얻었다면 중간지점을 낮춰서 더 잘라야하므로 왼쪽으로 탐색한다.

반대로 목표치보다 크게 얻었으면 중간지점을 높혀줘 오른쪽으로 탐색한다.

while lo <= hi:
    ...

    # 총 나무의 양이 목표치보다 작으면
    # 왼쪽으로 탐색해서 더 짧게 자르기
    if total < m :
        hi = mid - 1
    # 총 나무의 양이 목표치보다 크면
    # 오른쪽으로 탐색해서 더 길게 자르기
    else :
        result = mid
        lo = mid + 1

Untitled

</aside>