jusung-c
으 하기싫어
jusung-c
  • 공부 기록 (96)
    • Spring (42)
      • Spring 기초 이론 (8)
      • Spring 핵심 원리 - 기본 (9)
      • Blog 만들기 with SpringBoot (25)
    • JAVA (7)
      • Java 문법 (2)
      • 객체지향의 사실과 오해 (5)
    • Algorithm (47)
      • 자료구조 (3)
      • 완전탐색 (22)
      • 정렬 (4)
      • 이분탐색 (12)
      • 투 포인터 (4)
hELLO · Designed By 정상우.
jusung-c

으 하기싫어

BOJ 2110 - 공유기 설치
Algorithm/이분탐색

BOJ 2110 - 공유기 설치

2022. 5. 8. 22:42

문제

 

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

 

2110번: 공유기 설치

첫째 줄에 집의 개수 N (2 ≤ N ≤ 200,000)과 공유기의 개수 C (2 ≤ C ≤ N)이 하나 이상의 빈 칸을 사이에 두고 주어진다. 둘째 줄부터 N개의 줄에는 집의 좌표를 나타내는 xi (0 ≤ xi ≤ 1,000,000,000)가

www.acmicpc.net

 

  • 수직선 위 N개의 집 (2 ≤ N ≤ 200,000)
  • 각 집의 좌표 xi (0 ≤ xi ≤ 10억)
  • 공유기 C개 (2 ≤ C ≤ N)

 

 

아이디어

집이 5개이고 공유기가 3개인 경우

 

C개의 공유기를 몇몇 집에 설치할 것인데 가장 인접한 공유기 사이의 거리를 최대가 되도록 설치할 것이다.

' 최대 ' 라는 키워드가 나왔으므로 이분탐색을 먼저 생각해보았다.

 

원래 문제

C개의 공유기를 설치했을 때, 가장 인접한 공유기 사이의 최대 거리는 얼마인가?

 

최대 인접 거리를 매개 변수 D로 설정 후 문제를 뒤집어서 Yes or No 문제로 바꾼다.

 

뒤집어서 만든 Yes or No 문제

두 공유기 사이 거리가 D일 때 공유기 C개를 설치할 수 있는가? Yes or No

Yes인 것 중 가장 큰 값이 정답이 될 것이다. 

 

 

Yes or No 문제 풀이

어떤 거리 D 만큼 거리를 둘 때, 공유기 C개를 설치할 수 있는 지 알기 위해서는 주어진 집들의 좌표를 정렬한 후에 제일 왼쪽 집부터 되는 대로 전부 설치해보는 방법을 사용한다. 

 

D가 1일 경우

1 2 4 8 9

최대 5개의 공유기를 설치할 수 잇다.

 

D가 2일 경우

1 4 8, 1 4 9, 2 4 8, 2 4 9

최대 3개의 공유기를 설치할 수 있다.

 

D가 3일 경우

1 4 8, 1 4 9 

최대 3개의 공유기를 설치할 수 있다.

 

이와같이 왼쪽부터 그냥 되는 대로 전부 설치해보면 어짜피 정렬이 된 상태라서 애초에 오른쪽 집으로 갈 수록 인접한 공유기의 거리가 짧아지기 때문이다. D만큼의 거리를 확보하기 위해서 제일 왼쪽집부터 설치해나가면서 가능한 공유기 설치 개수를 카운트한다.

 

 

시간 복잡도

  • 왼쪽부터 차례대로 설치해서 확인하면 되기 때문에 Yes or No 문제를 푸는 데에는 O(N)의 시간이 걸린다.
  • N개의 집들을 정렬하는 데에는 최대 O(N logN)의 시간이 걸린다.
  • 이분탐색 진행 시 탐색 범위가 최대 1~10억이므로 최대 질문 수는 log10억이 돼서 O(log 10억0의 시간이 걸린다.
  • 총 시간 복잡도는 O(N logN + N log 10억) 이므로 N의 최댓값이 20만이라서 2초안에 풀이가 가능하다.

 

구현

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static int N, C;
    static int[] home;

    static void init() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        N = Integer.parseInt(st.nextToken());
        C = Integer.parseInt(st.nextToken());

        home = new int[N + 1];
        for (int i = 1; i <= N; i++) {
            home[i] = Integer.parseInt(br.readLine());
        }
    }

    static void pro() throws IOException {
        // 집들의 좌표 정렬
        Arrays.sort(home);

        // 이분탐색
        int L = 1;
        int R = 1000000000;
        int ans = 0;

        while (L <= R) {
            int mid = (L + R) / 2;

            // Yes인 경우
            if (YesOrNo(mid)) {
                L = mid + 1;
                ans = mid;

            // No인 경우
            } else {
                R = mid - 1;
            }
        }

        bw.write(ans+" ");
    }

    // 거리가 D일 때 C개 만큼의 공유기를 설치할 수 있는가? Yes or No?
    private static boolean YesOrNo(int D) {
        // 제일 왼쪽집부터 설치
        int cnt = 1;
        // 마지막 설치 위치
        int last = home[1];

        // 왼쪽에서부터 설치 시작
        for (int i = 2; i <= N; i++) {
            // 마지막 설치 위치로부터 D만큼 떨어진 곳에 설치
            if (home[i] - last >= D) {
                cnt++;
                last = home[i];
            }
        }

        // Yes or No
        if (cnt >= C) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) throws IOException {
        init();

        pro();

        bw.close();
    }

}

 

 

 

 

 

저작자표시 비영리 변경금지 (새창열림)

'Algorithm > 이분탐색' 카테고리의 다른 글

BOJ 6236 - 용돈 관리  (0) 2022.05.09
BOJ 2343 - 기타 레슨  (0) 2022.05.09
BOJ 2512 - 예산  (0) 2022.05.02
BOJ 1654 - 랜선 자르기  (0) 2022.05.02
BOJ 2805 - 나무 자르기  (0) 2022.05.01
    'Algorithm/이분탐색' 카테고리의 다른 글
    • BOJ 6236 - 용돈 관리
    • BOJ 2343 - 기타 레슨
    • BOJ 2512 - 예산
    • BOJ 1654 - 랜선 자르기
    jusung-c
    jusung-c

    티스토리툴바