[백준] 2805. 나무 자르기

Minji·2024년 1월 5일

2805번: 나무 자르기

문제 접근 🤔


  • 주어진 나무들을 자르고 남은 나무들의 길이 합이 최소한 m 이상이 되도록 하는 자르는 길이의 최댓값을 찾는 문제다.
  • 이분 탐색을 이용하면 길이를 찾는 시간 복잡도를 줄일 수 있다.
  • 구하는 것은 나무를 자를 길이이므로 탐색을 진행할 범위는 (0, max(trees)) 이다.
  • 범위의 중간값을 mid 라 하고 mid 보다 큰 나무가 존재하면 자르고 남은 길이를 합해준다.
  • 이 길이의 합이 m 과 같다면 구하는 최댓값이 현재의 mid 값이므로 저장해주고 반복문을 종료한다.
  • 크다면 나무를 자를 수는 있지만 최댓값인지 모르므로 현재까지 저장된 값과 현재의 mid 중 더 큰 값을 저장하고 범위의 시작 위치를 mid 의 오른쪽으로 옮겨준다.
  • 작다면 범위의 끝을 mid 의 왼쪽으로 옮겨준다.
  • 이 과정이 완료되면 문제의 조건을 만족하는 최댓값을 구할 수 있다.


놓쳤던 부분 😅


  • 없음


코드 😁


파이썬 코드(480 ms)

n, m = map(int, input().split())
trees = list(map(int, input().split()))
low, high = 0, max(trees)
maxLen = 0

while low <= high:
    mid = (low + high) // 2

    cutLen = 0
    for tLen in trees:
        if mid < tLen:
            cutLen += tLen - mid

    if m == cutLen:
        maxLen = mid
        break
    elif m < cutLen:
        maxLen = max(mid, maxLen)
        low = mid + 1
    else:
        high = mid - 1

print(maxLen)

자바스크립트 코드(1028 ms)

const fs = require('fs');
const filePath = process.platform === 'linux' ? '/dev/stdin' : __dirname + '/input.txt';
const [L, datas] = fs.readFileSync(filePath).toString().trim().split('\n');

const solution = ([n, m], trees) => {
  let [low, high] = [0, Math.max(...trees)];
  let maxLen = Number.MIN_SAFE_INTEGER;

  while (low <= high) {
    let mid = ~~((low + high) / 2);
    let cutLen = trees.reduce((sum, tLen) => (mid < tLen ? sum + tLen - mid : sum), 0);

    if (m === cutLen) {
      maxLen = mid;
      break;
    } else if (m < cutLen) {
      maxLen = Math.max(mid, maxLen);
      low = mid + 1;
    } else {
      high = mid - 1;
    }
  }
  console.log(maxLen);
};

solution(L.split(' ').map(Number), datas.split(' ').map(Number));
profile
기록을 좋아하는 프론트엔드 개발자입니다.

0개의 댓글