[백준 2805][Kotlin] 나무 자르기

Updated:

문제 링크

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

코드

  
fun cutTree(trees: List<Int>, saw: Long): Long {  
    var result: Long = 0  
    for (t in trees) {  
        if (t > saw) {  
            result += (t - saw)  
        }  
    }  
    return result  
}  
  
fun main() {  
    val (n,m) = readln().split(' ').map {it.toLong()}  
    var sum: Long = 0  
    val trees = readln().split(' ').map {  
        val intValue = it.toInt()  
        sum += intValue  
        intValue  
    }  
    var low: Long = 0  
    var high: Long = sum  
    var mid: Long = 0  
    var result = mid  
  
    while (low <= high) {  
        mid = (low + high)/2  
        val value = cutTree(trees, mid)  
        when {  
            (value == m) -> {  
                print(mid)  
                return  
            }  
            (value < m) -> {  
                high = mid - 1  
            }  
            else -> {  
                low = mid + 1  
                result = mid  
            }  
        }  
    }  
    print(result)  
}

설명

자를 수 있는 가장 큰 나무 길이는 주어진 나무 길이의 합(sum)과 같기 때문에 0에서 부터 sum까지 이진탐색을 수행한다.
이진탐색을 한 번 돌 때마다 얻을 수 있는 나무 길이를 비교하여 중간 값(mid)을 산정하며 계산한다.
이때 주의해야할 점은 문제에서 요구하는 것처럼 절단기에서 설정할 수 있는 높이의 최댓값이다. m보다 더 많은 나무를 잘라서까지 필요한 나무를 확보해야한다. 때문에 이진탐색 시 자른 나무 길이(value)가 필요한 나무(m)보다 클 때 result 변수에 대입하여 mid가 m보다 작은 상태로 탐색 종료 시 result를 반환하도록 했다.

후기

알고리즘에는 문제가 없었는데 계속 틀렸던 이유는 오버플로우 때문이었다.
문제 조건에 나무의 길이의 합이 (1백만) X (10억)까지 가능한데 자료형을 Int형으로 계산했었으니 오버플로우가 일어나 정상적인 계산이 되지 않았었다.
Int형의 범위는 약 -21억~21억이므로 문제에서 범위가 나오면 이를 염두해두고 Int와 Long(약 -992경~992경) 중 무엇을 정수 크기로 사용할지 결정하자.

Leave a comment