[ 백준 ] 1477 / 휴게소 세우기

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
50/228
post-thumbnail

# Appreciation

/*
 * Problem :: 1477 / 휴게소 세우기
 *
 * Kind :: Binary Search
 *
 * Insight
 * - 최댓값의 최솟값을 구한다
 *   최솟값의 최댓값을 구한다
 *   보통은 이분 탐색으로 풉니다
 *   by 코드플러스 백준님의 강의 중에서
 *   + 휴게소가 없는 구간의 길이가 커질수록
 *     휴게소를 덜 지어도 된다 => 단조 증가
 *     # 휴게소가 없는 구간의 길이를 정하고
 *       휴게소를 세워서 지어진 휴게소 개수가 M개 이하이면
 *       정한 길이를 바탕으로 휴게소를 지을 수 있다
 *       -> 정한 길이의 최댓값을 이분 탐색을 통해 찾아주자
 *
 * Point
 * - 하한, 상한을 정해야 하는데
 *   상한은 초기 시작점, 끝점도 휴게소가 세워진 것으로 가정했을 때
 *   각 휴게소에 인접한 휴게소들간의 거리의 최댓값이다
 *   + 하한은 1 이다 (최소 인접한 휴게소들간의 거리)
 *     상한처럼 (똑같은 가정아래) 인접한 휴게소들간의 거리의 최솟값이 아니다!
 *     휴게소가 세워지면서 얼마든지 거리가 좁혀질 수 있기 때문이다
 *     # 괜히 최적화한답시고 하한을 (L+N+M-1)/(N+M) 잡아 고생했다 ㅠㅠ
 *
 * - 휴게소가 없는 구간의 길이를 m 이라 할때,
 *   서로 인접한 어떤 휴게소의 위치가 a, b (a < b) 라면
 *   그 사이 세워야 하는 휴게소의 개수는 (b-a-1)/m 이다
 *   + 처음에는 cpos 라는 현재 위치를 나타내는 변수에
 *     while 문을 넣어서 cpos += m, cnt++ 라는 로직을 사용했지만
 *     처음의 식으로 구하는 것이 훨씬 깔끔하고 직관적이다!
 */

# 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 N, M, L;
    cin >> N >> M >> L;
    int A[N+2];
    for (int i=1; i<=N; i++)
        cin >> A[i];

    // Process
    A[0] = 0, A[N+1] = L; /* A[0] = 시작점, A[N+1] = 끝점 */
    sort(A, A+(N+2));
    int l = 1, r = A[0]; /* 하한, 상한 */
    for (int i=1; i<N; i++) {
        r = max(r, A[i]-A[i-1]);
    } r = max(r, L-A[N-1]);

    int ans = -1;
    while (l <= r) {
        int m = (l+r)/2; /* 휴게소가 없는 구간의 길이 */
        int cnt = 0; /* 지은 휴게소 개수 */
        for (int i=1; i<N+2; i++) {
            cnt += (A[i]-A[i-1]-1)/m;
        }

        if (cnt > M) {
            l = m+1;
        } else {
            ans = m; /* 반드시 M개를 모두 지어야 하는데
                      * 현재 m 에 맞춰 지은 휴게소 개수 cnt 가 M 이하라면
                      * 그냥 m 을 유지하게끔 다른 구간에 나머지 휴게소를 적당히 지으면 됨 */
            r = m-1;
        }
    }

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

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

0개의 댓글