알고리즘/문제풀이

[백준 3632번] Drying

Ohnim · 오님 2024. 8. 25. 00:24

문제 링크

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

 

문제 요약

\(N\)개의 빨래와 각각의 빨래가 가지고 있는 초기 물의 양이 주어진다. 모든 빨래는 1분마다 물의 양이 1씩 줄어들며, 매 분마다 한 개의 빨래를 선택해 라디에이터에 올릴 수 있다. 라디에이터에 올린 빨래는 물의 양이 1분마다 \(K\)씩 줄어든다. 모든 빨래의 물의 양이 0이 되는 최소한의 시간을 구하는 문제이다.

 

문제 풀이

만약 \(X\)분 내에 모든 빨래를 말릴 수 있는 방법이 존재한다면, \(X\)분보다 더 큰 시간 내에서도 모든 빨래를 말릴 수 있다. 반대로 \(X\)분 내에 모든 빨래를 말릴 수 없다면, \(X\)분 보다 더 작은 시간 내에 모든 빨래를 말릴 방법은 존재하지 않는다. 이 특성을 이용해 최적화 문제를 결정 문제로 바꿀 수 있고, 이분 탐색을 이용해 답을 빠르게 찾을 수 있다.

 

이제 \(X\)분 내에 모든 빨래를 말릴 수 있는지 확인하는 방법을 알아보자. 모든 빨래를 \(X\)분 내로 말리기 위해서는 라디에이터를 최선의 방법으로 사용해야 한다. 빨래 \(i\)가 가지고 있는 물의 양을 \(A[i]\)라고 하자. 만약 \(A[i]\)가 \(X\)보다 작거나 같다면, 이 빨래는 라디에이터를 사용하지 않아도 된다. 그러나 \(A[i]\)가 \(X\)보다 크다면, 이 빨래를 \(X\)분 내로 말리기 위해 라디에이터를 최소한의 횟수로 사용해야 한다.

 

이 경우, \(A[i]\)에서 \(X\)를 뺀 값은 라디에이터를 이용해 추가적으로 제거해야 하는 물의 양이다. 이 값을 \(K - 1\)로 나누고 올림 한 값이 이 빨래를 \(X\)분 내에 말리기 위해 필요한 최소 라디에이터 사용 횟수다. 모든 빨래에 대해 이 값을 계산한 뒤 더한 값이 \(X\)를 초과하면, \(X\)분 내에 모든 빨래를 말릴 수 없다는 뜻이다.

 

\(K\)가 1인 경우는 예외 케이스인데, \(A[i]\)가 \(X\)를 초과하면 라디에이터를 사용해도 빨래를 \(X\)분 내에 말릴 수 없으므로 불가능하다고 판단하면 된다.

 

소스 코드

더보기
더보기
#include <stdio.h>

int n;
long long k, A[100010];

bool isPossible(long long x) {
    long long tot = 0;
    
    for (int i = 0 ; i < n ; ++i) {
        if (A[i] > x) {
            if (k == 1) {
                return false;
            }
            
            long long up = A[i] - x;
            long long down = k - 1;
            
            tot += (up / down) + (up % down ? 1 : 0);
        }
    }
    
    return tot <= x;
}

int main() {
    scanf("%d", &n);
    
    for (int i = 0 ; i < n ; ++i) {
        scanf("%lld", &A[i]);
    }
    
    scanf("%lld", &k);
    
    long long lo = 0, hi = 1e9 + 10;
    
    while (lo < hi) {
        long long mid = (lo + hi) / 2;
        
        if (isPossible(mid)) {
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    
    printf("%lld\n", lo);
}