티스토리 뷰

BOJ/Easy

BOJ 2110 공유기 설치

arnold518 2018. 12. 20. 20:18

문제

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

주어진 점들중 c개를 골랐을 때 가장 멀리 떨어질 수 있도록 하는 거리를 구하는 문제이다.

 

풀이

종만북에는 "DARPA" 라는 이름으로 실려 있는 문제이다.

문제가 "최적화 문제" 이니까, 한번쯤은 패러매트릭 서치를 생각해야 정상이다.(!!)

 

출력해야 하는 답은 "몇 m 떨어지게 설치하는 것이 최대인가?" 이니, 이것을 이분탐색의 인자로 놓고 구현한다.

이제 결정 문제를 풀어보도록 하자.

최소 d m 떨어져 있도록 선택했을 때, c개 이상으로 선택될 수 있는가? 라는 결정 문제이다.

 

첫번째 위치를 선택해야 될까?

선택하지 않은 해가 있다고 가정하면, 그 해에서 첫번째 값을 빼고 앞의 위치를 선택해도 된다.

그렇다! 그리디가 해법이다.

방금 Greedy Choice Property 를 증명했고, Optimal Substructure 은 자명하므로,

Greedy를 통해 공유기를 최대한 많이 배정한 후 c와 비교하면 된다.

 

이 문제에서 중요하게 봐야 할것은 구현이다.

나는 이 문제부터 이분탐색의 구현을 반 열린 구간으로 구현하기로 했다.

 

while(lo+1<hi) 를 놓고, 답은 상황에 맞게 가져다 사용하면 된다.

mid 는 반 열린구간이기 때문에 무조건 lo+hi >>1 이며,

헷갈릴 때에는 lo가 decision()을 만족 하는지를 따져 가며 반복문 불변식을 세우면 어렵지 않게 이해할 수 있다.

 

시간복잡도 : O(Nlog109)

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int MAXN = 2e5;

int n, c, arr[MAXN+10];

bool decide(int d)
{
    int i;
    int cnt=0;
    for(i=0; i<n;)
    {
        cnt++;
        int now=arr[i];
        while(i<n && now+d>arr[i]) i++;
    }
    return cnt>=c;
}

int main()
{
    cin.tie(0); cout.tie(0);
    ios_base::sync_with_stdio(false);
    int i, j;

    scanf("%d%d", &n, &c);
    for(i=0; i<n; i++) scanf("%d", &arr[i]);
    sort(arr, arr+n);

    int lo=0, hi=1e9;
    while(lo+1<hi)
    {
        int mid=(lo+hi)/2;
        if(decide(mid)) lo=mid;
        else hi=mid;
    }

    printf("%d", lo);
    return 0;
}

 

 

 

 

 

 

 

'BOJ > Easy' 카테고리의 다른 글

BOJ 1637 날카로운 눈  (0) 2018.12.23
BOJ 3090 차이를 최소로  (0) 2018.12.22
BOJ 2343 기타 레슨  (0) 2018.12.22
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함