기타등등/알고리즘 기록

[C++] 결정 알고리즘 - 마굿간 정하기

CodeJB 2021. 7. 29. 21:00

#include <stdio.h>
#include <algorithm>

using namespace std;
int N;

int Count(int size, int xi[]){//dvd개수
    int p = xi[1],i,cnt=1;
    for(i = 2; i <= N; i++){
        //뒤에 값들과 빼보다가
        //두 마굿간의 길이가 정답보다 크거나 같다면
        //말을 배치할 수 있음
        //그 자리에서 다음 마굿간과의 거리를 재서 크거나 같으면 말을 배치함
        //만약 정답이 3(mid == 3)이라면
        //마굿간 두 쌍의 거리가 둘 다 3보다 커야지
        //두 마굿간 중 가까운 마굿간 쌍의 거리가 3으로 설명할 수 있으므로
        if(xi[i] - p >= size){
            cnt++;
            p = xi[i];
        }
    }
    
    return cnt; //배치한 말의 수
}

int main() {
    int C,lt=1,rt,mid,i,res;
    scanf("%d %d",&N,&C);
    
    int *xi = new int[N+1];
    
    for(i = 1; i <= N; i++){
        scanf("%d",&xi[i]);
    }
    
    sort(xi+1, xi + (N+1));
    
    rt = xi[N];
    
    while(lt <= rt){
        mid = (lt+rt)/2; //정답 하나 뽑아보기
        if(Count(mid,xi) >= C){//이거 정답 맞아? 넘겨줌
            // cnt가 3보다 작으면 말 3마리 배치를 못한다는 거니까 오답
            // 첫 반복때 Mid가 5인데 그럼 오답임.
            
            res = mid;
            lt = mid+1;
        }
        else rt = mid-1;
    }
    printf("%d\n",res);
    
    delete[] xi;
    
    return 0;
}
  • 뮤직비디오 문제와 푸는 방식이 동일하다
  1. 1~8 사이에 정답 있을 것이라고 가정하고 말 세마리를 배치할 수 있는지 이분검색을 시작한다.
  2. 만약 정답(가장 가까운 두 말의 최대거리)을 4(mid)라고 한다면 말을 두마리밖에 배치하지 못하기 때문에 rt를 줄인다. 1~3
  3. 만약 정답을 2(mid)라고 한다면 말을 세 마리 배치할 수 있기 때문에 정답이다. 하지만 더 좋은 정답을 찾기위해 이분탐색은 계속한다
  4. 만약 정답을 3(mid)라고 한다면 말을 세 마리 배치할 수 있기 때문에 정답이다. 2와 3이 있지만 최대거리를 구하기 때문에 3이 정답이 된다.
*주의
이분 검색을 통해 정답을 2로 정해놓고 Count함수로 보내게 되면, 1 - 4 - 8 에 말을 배치하여 끝내게된다. 무조건 크거나 같으면 cnt++을 하기 때문이다.
정답은 2로 정해놓고 Count로 보냈는데 가장 가까운 말의 거리는 3이된다. 이러면 올바르게 동작했다고 볼 수 있나? : YES
정답을 2로 정해놓고 보내긴 했으나, 실제로는 1 - 4 - 8로도 배치가 가능하다라는 방안을 리턴받게 되는 것이다.
그럼 결국 다음 단계에서 2보다 더 좋은 답안인 3을 얻게 되는 것이다.

결국 Count함수로 보낼 때에는 "이거 정답 맞아?"라고 보내는 것이고
돌려 받을 때에는 "정답이 아니야" || "정답이야" || "정답이긴 한데, 더 좋은 답안이 있으니까 다시 보내봐" 정도의 논리가 성립된다. 때문에, Count함수에서의 조건문은 비교적 간단해도 괜찮다는 결론이 나온다.(다른 문제를 많이 풀어봐야겠다.)
https://www.inflearn.com/course/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/dashboard