본문 바로가기
알고리즘/백준

[백준] 2110번 공유기 설치 (C++)

by sb99 2022. 6. 20.

문제 링크

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개의 집이 있고 각각의 집의 좌표는 0부터 1,000,000,000 값을 갖는다.

하나의 집에 최대 1개의 공유기를 총 C개 설치하는데, 가장 인접한 두 공유기 사이의 최대 거리를 구해야 한다.

 

사고 과정

집의 좌표는 크기 순서대로 주어지지 않지만 집 사이의 거리는 좌표의 순서에 영향을 받기 때문에,

집의 좌표를 입력 받고 오름차순으로 정리해줘야 한다는 생각이 들었다.

정렬 이후에 집에 공유기를 배치 해야 하는데, 모든 경우의 수를 따지면 O(N^2)이 되기 때문에 이분 탐색을 활용해야 했다.

 

하지만 이분 탐색을 어디에 적용해야 하는지 감이 안잡혔다..

입력 받은 집의 좌표에 대해 적용하자니 공유기를 여러 개 배치해야 하기 때문에 

사실상 모든 경우의 수를 따지는 것과 다름이 없고...

좌표에 이분 탐색을 적용하자니 공유기는 집에만 설치할 수 있기 때문에

선택된 좌표에 집이 존재 하는지와 다른 좌표는 또 어떻게 선택할 지 막막했다.

 

해결 방법

결국 다른 블로그를 참고해서 이해함ㅠ

https://jaimemin.tistory.com/966

 

결론은 이분 탐색을 거리에 적용해야 했다.

1. 입력받은 좌표를 오름차순으로 정렬한다.

2. 최소 거리와 최대 거리를 설정한다.

3. 거리에 대한 이분 탐색을 진행한다. 이 때 설정한 거리가 문제의 조건에 부합하는지 확인한다.

4. 3번 조건을 충족하는 거리 중, 최대 거리를 출력한다.

 

예시

백준에 제시된 예시를 활용해보자.

 

코드

#include <iostream>
#include <algorithm>

using namespace std;

void init();
void input();
bool isPossible(int num);
void solve();

int N, C;
int arr[200001];

void init()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
}

void input()
{
    cin >> N >> C;

    for (int i = 0; i < N; i++)
    {
        cin >> arr[i];
    }
}

bool isPossible(int num)
{
    int cnt = 1;
    int prev = arr[0];

    for (int i = 1; i < N; i++)
    {
        if (arr[i] - prev >= num)
        {
            cnt++;
            prev = arr[i];
        }
    }

    if (cnt >= C)
        return true;
    return false;
}

void solve()
{
    sort(arr, arr + N);

    // 최소거리, 최대거리
    int low = 1;
    int high = arr[N - 1] - arr[0];
    int result = 0;

    while (low <= high)
    {
        int mid = (low + high) / 2;
        if (isPossible(mid))
        {
            result = max(result, mid);
            low = mid + 1;
        }
        else
            high = mid - 1;
    }

    cout << result;
}

int main()
{
    init();
    input();
    solve();

    return 0;
}

 

'알고리즘 > 백준' 카테고리의 다른 글

[백준] 17298번 오큰수 (C++)  (0) 2022.07.02
[백준] 1300번 K번째 수 (C++)  (0) 2022.06.27
[백준] 3079번 입국심사 (C++)  (0) 2022.06.27
[백준] 3020번 개똥벌레 (C++)  (0) 2022.06.24
[백준] 2470번 두 용액 (C++)  (0) 2022.06.23

댓글