백준 1477번 - 휴게소 세우기 (재풀이)

황제연·2025년 1월 10일
0

알고리즘

목록 보기
148/169
post-thumbnail

문제 탐색하기

입력 자료 정리

  1. n은 설치된 휴게소 개수, m은 설치할 휴게소 개수, l은 고속도로의 최대 길이다
  2. 이어서 들어오는 n개의 입력값은 이미 설치된 휴게소다

해결방법 추론

  1. 문제를 보자마자 이분탐색으로 푸는 문제라고 생각하기는 했는데...
    입력값이 너무 작아서 브루트 포스로도 가능하지 않을까 생각했다
  2. 브루트 포스로 가능한 방법을 생각해봤는데, m개의 휴게소를 l개의 고속도로에 설치할 때 경우의 수를 모두 고려하면 될 것이다
  3. 하지만 해당 방법은 1000^100이라는 시간복잡도가 발생하기 때문에, 선택할 수 없다
  4. 따라서 브루트포스로는 불가능하고 다른 방법으로 해결해야겠다고 생각했다
  5. 휴게소가 없는 구간의 최댓값의 최솟값을 구하는 문제다.
    조금 말장난 같은데 정리하면 추가로 설치하는 휴게소를 모두 설치했을 때 휴게소간 차이를 구하고
    그 구간 중에 최댓값을 구하는 것이다.
  6. 그리고 가능한 모든 경우의 수를 확인한뒤, 그 최댓값들 중에서 최솟값을 구하면 된다
  7. 그렇다면 문제를 어떻게 해결할 수 있을까? 조금 편하게 풀려면 휴게소간 차이를 구한 다음
    각 차이마다 휴게소가 없는 구간의 최댓값 간격으로 설치한 다음 가능한 개수를 구하면 될것이다
  8. 그리고 그 개수를 기준으로 최댓값 간격을 조절하면 될 것이다!
  9. 이때 이분탐색을 이용해서 최댓값 간격을 log단위로 조절하면 문제를 해결할 수 있을 것이다
  10. 해결방법의 틀은 나왔고, 이 문제에서 주의할 점이 몇가지 있어 미리 정리했다
  • 이미 설치된 휴게소 끼리의 간격만 구하면 안된다. 0번 지점과 가장 가까운 휴게소간의 차이,
    l번 지점과의 가장 먼 휴게소간의 차이도 계산해야한다
  • 이분탐색의 범위는 휴게소를 설치할 수 있는 위치로 판단한다. 따라서 1~l-1범위로 지정해야한다
  • 두 지점의 차이는 휴게소를 설치할 수 있는 계산해야한다. 즉, 차이를 계산하는 두 지점은 제외한다 (0번 지점과 5번 지점에 설치되면 1,2,3,4만 설치할 수 있다.)
  1. 이제 주의점을 생각하고 추론한 방법으로 구현하면 된다!

시간복잡도 계산

  1. 이분탐색의 시간복잡도는 log l이다.
  2. 이때 이분탐색마다 모든 휴게소 간격을 확인하며 가능한 개수를 파악하므로 n의 연산이 추가로 발생한다
  3. 따라서 시간복잡도는 O(n x log l)이 되며 시간제한안에 문제를 해결할 수 있다

코드 설계하기

입력값 상태 관리

  1. 각 크기는 변수로 관리하며, n의 값들은 int형 1차원 배열로 관리한다
  2. n의 값을 보관하는 배열은 n+2의 크기로 선언한다. 고속도로의 시작과 끝도 보관하기 위함이다.
  3. 0번 인덱스와 n+1번 인덱스에 0과 l을 넣고, 차이를 계산하기 위해 오름차순 정렬을 한다
  4. 배열간 차이만 구해도 되긴 하는데, 조금더 편하게 하기 위해 차이를 관리할 리스트를 선언했다
  5. 해당 리스트에 두 배열간 차이 - 1을 넣어준다.
  6. 이분탐색을 위한 left와 right를 각각 1과 l-1로 선언한다
  7. 또한 정답을 위한 ans배열을 Integer.MAX_VALUE로 선언한다. 최솟값을 구하기 위함이다

구현 코드 설계

  1. 이분탐색을 시작한다. count 변수를 0으로 초기화해서 선언한다
  2. 모든 차이를 탐색하며, mid로 나눈 몫을 count에 더한다
  3. count와 m을 비교해서 만약 m보다 count가 큰 경우 left의 범위를 조절한다
    너무 크기가 작아서 휴게소 사이에 많이 설치할 수 있기 때문이다.
  4. 또한 3번의 경우는 정답으로 체크하지 않는다. m개만큼 설치하라고 했기 때문에 정답으로 선정할 수 없다
  5. 만약 3번이 아닌 경우 right의 범위를 조절해서 최적의 정답을 탐색한다
  6. 이때는 정답과 mid를 비교해서 더 작은 값으로 갱신한다
  7. 5번에서 count가 m보다 작은 경우도 포함되는데, m개만큼 설치되지는 않았지만 최댓값보다 작은 간격으로 설치가 가능하며 이 경우 정답에 변동을 주지 않기 때문이다

출력값 설계

  1. 완성한 ans를 출력하면 정답이 된다.

정답 코드

import java.io.*;
import java.util.*;


public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        int l = Integer.parseInt(st.nextToken());
        int[] arr = new int[n+2];
        arr[0] = 0;
        arr[n+1] = l;
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i < n+1; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        Arrays.sort(arr);
        List<Integer> lists = new ArrayList<>();
        for (int i = 1; i < n+2; i++) {
            lists.add(arr[i] - arr[i-1]-1);
        }

        int left = 1;
        int right = l-1;
        int ans = Integer.MAX_VALUE;


        while(left <= right){
            int mid = (left + right)/ 2;
            int count = 0;
            for (int i = 0; i < n+1; i++) {
                count += lists.get(i) / mid;
            }
            if(count > m){
                left = mid + 1;
            }else{
                right = mid - 1;
                ans = Math.min(ans, mid);
            }
        }

        bw.write(ans+"");

        br.close();
        bw.close();
    }

}

문제 링크

1477번 - 휴게소 세우기

profile
Software Developer

0개의 댓글