[ 백준 ] 1654 / 랜선 자르기

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
124/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 1654 / 랜선 자르기
 *
 * Kind :: Binary Search
 *
 * Insight
 * - 전형적인 이분탐색 문제다
 *   + 자르는 랜선의 길이가 길어질수록 개수는 적어지고
 *     자르는 랜선의 길이가 짧아질수록 개수는 많아진다
 *     # 단조감수함수, 한 번 탐색할 때마다 탐색범위를 반으로 줄일 수 있다
 *       -> 이분탐색으로 풀자
 *
 * Point
 * - 자르는 랜선의 길이가 될 수 있는 최댓값은
 *   주어진 랜선들의 길이중 최댓값이다
 *   + 10, 100, 1000 이 주어졌을 때, 3개를 만들어야 한다면
 *     자르는 랜선의 길이를 333 으로 해서 1000 짜리에서 3개를 만들어내면 된다
 *     굳이 주어진 랜선들을 모두 잘라서 활용할 필요는 없다
 *   + 주어진 랜선들의 길이중 최댓값보다 큰 길이로 랜선들을 잘랐을 때
 *     만들어지는 랜선의 개수는 0개다
 *
 * - max(랜선의 길이)가 max(int) 이므로
 *   이분탐색에서 중간을 구할 때 Overflow 가 일어날 수 있다
 *   + long 으로 바꾸어주자
 *   + 혹은, (l+r)/2 가 아닌 l/2+r/2 로 하여 Overflow 를 피할 수 있다
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <algorithm>

using namespace std;

#define endl '\n'

// Set up : Global Variables
/* None */

// Set up : Functions Declaration
/* None */


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    int K, N;
    cin >> K >> N;
    int L[K];
    for (int i=0; i<K; i++) {
        cin >> L[i];
    }

    // Process
    long l = 1; /* 자르는 랜선의 길이가 될 수 있는 최솟값 */
    long r = *max_element(L, L+K); /* 자르는 랜선의 길이가 될 수 있는 최댓값 */

    long ans = -1;
    while (l <= r) {
        long m = (l + r) / 2;
        long cnt = 0;
        /* 자르는 랜선의 길이가 m 일 때, 만들어진 랜선의 개수 cnt */
        for (int len : L) {
            cnt += len / m;
        }

        if (cnt >= N) { /* 만들어진 랜선의 개수가 N 이상이면 */
            ans = m; /* 현재 자른 길이 m 을 답으로 갱신 */
            l = m+1; /* 현재 자른 랜선의 길이보다 작거나 같은 길이는 탐색하지 않아도 됨 */
        } else { /* 만들어진 랜선의 개수가 N 미만이면 */
            r = m-1; /* 현재 자른 랜선의 길이보다 크거나 같은 길이는 탐색하지 않아도 됨 */
        }
    }

    // Control : Output
    cout << ans << endl;
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글