문제 링크: https://www.acmicpc.net/problem/1477

 

1477번: 휴게소 세우기

첫째 줄에 현재 휴게소의 개수 N, 더 지으려고 하는 휴게소의 개수 M, 고속도로의 길이 L이 주어진다. 둘째 줄에 현재 휴게소의 위치가 공백을 사이에 두고 주어진다.

www.acmicpc.net

 

▶문제

다솜이는 유료 고속도로를 가지고 있다. 다솜이는 현재 고속도로에 휴게소를 N개 가지고 있는데, 휴게소의 위치는 고속도로의 시작으로부터 얼만큼 떨어져 있는지로 주어진다. 다솜이는 지금 휴게소를 M개 더 세우려고 한다.

다솜이는 이미 휴게소가 있는 곳에 휴게소를 또 세울 수 없고, 고속도로의 끝에도 휴게소를 세울 수 없다. 휴게소는 정수 위치에만 세울 수 있다.

다솜이는 이 고속도로를 이용할 때, 모든 휴게소를 방문한다. 다솜이는 휴게소를 M개 더 지어서 휴게소가 없는 구간의 길이의 최댓값을 최소로 하려고 한다. (반드시 M개를 모두 지어야 한다.)

예를 들어, 고속도로의 길이가 1000이고, 현재 휴게소가 {200, 701, 800}에 있고, 휴게소를 1개 더 세우려고 한다고 해보자.

일단, 지금 이 고속도로를 타고 달릴 때, 휴게소가 없는 구간의 최댓값은 200~701구간인 501이다. 하지만, 새로운 휴게소를 451구간에 짓게 되면, 최대가 251이 되어서 최소가 된다.


▶입력

첫째 줄에 현재 휴게소의 개수 N, 더 지으려고 하는 휴게소의 개수 M, 고속도로의 길이 L이 주어진다. 둘째 줄에 현재 휴게소의 위치가 공백을 사이에 두고 주어진다.


▶출력

첫째 줄에 M개의 휴게소를 짓고 난 후에 휴게소가 없는 구간의 최댓값의 최솟값을 출력한다.


▶해설

휴게소 간격중에 가장 큰 값을 가장 작게 만들면 되는 문제입니다.

 

처음에는 휴게소 사이의 값을 정렬해서 가장 큰 값들 먼저 2로 나눠서 설치하면 풀리겠는데? 하고 시도해봤습니다.

하지만 모든 경우의 수를 충족시키진 못했습니다.

 

그래서 거리에 초점을 맞춰 이분 탐색으로 시도했습니다.

 

left = 1 (거리가 0인 것은 굳이 신경쓸 필요가 없기 때문)

right = l-1 (거리가 l인 것은 존재할 수 없기 때문)

 

dis = (left+right)/2입니다. (휴게소 간격)

 

 

(arr[i]-arr[i-1]-1)/dis -> 휴게소 사이에 dis의 거리를 만족하는 휴게소를 몇 개 설치가 가능한지 확인합니다.

1~n+1까지 확인합니다. (고속도로 시작점 0과 끝지점 l이 포함되기 때문)

 

개수가 m개를 넘을 때 참을 반환합니다. 더 큰 간격이 필요하므로 left = dis+1 됩니다.

개수가 m개와 작거나 같을 때 거짓을 반환합니다. 더 작은 간격이 필요하므로 right=dis-1 됩니다.

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {

    static int n, m, l;
    static int[] arr;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        l = Integer.parseInt(s[2]);
        arr = new int[n+2];
        arr[0]=0;
        arr[n+1]=l;
        makeArr(br);
        int result = solve();

        System.out.println(result);
    }

    private static int solve() {
        Arrays.sort(arr);
        int left = 1;
        int right = l-1;
        while (left <= right) {
            int dis = (left + right) / 2;
            if (make_store(dis)) {
                 left = dis + 1;
            } else {
                 right = dis - 1;
            }
        }
        return left;
    }
    private static boolean make_store(int dis){
        int count=0;
        for(int i=1; i<=n+1; i++){
            count+=(arr[i]-arr[i-1]-1)/dis;
        }
        if(count>m){
            return true;
        }
        else{
            return false;
        }
    }

    private static void makeArr(BufferedReader br) throws IOException {
        String[] s1 = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            arr[i+1] = Integer.parseInt(s1[i]);
        }
    }
}