[프로그래머스] 입국심사

1 minute read

문제 설명

n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.

처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.

모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.

입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 입국심사를 기다리는 사람은 1명 이상 1,000,000,000명 이하입니다.
  • 각 심사관이 한 명을 심사하는데 걸리는 시간은 1분 이상 1,000,000,000분 이하입니다.
  • 심사관은 1명 이상 100,000명 이하입니다.

풀이

30분
예전에 풀었지만 기억은 나지 않는 문제였는데, 다시 풀어도 풀이가 똑같았다. 우선 문제 조건에서 1,000,000,000명을 심사관 1명이 1,000,000,000분을 심사하는 경우를 생각했다. 그러면 10^12 의 시간이 걸리는데, 이것이 long long 범위인 2^63 - 1의 범위 안에 들어가는 것을 확인했다. 이진탐색을 구현하고 테스트코드를 통과해서 제출했는데, 줄줄이 실패했다.

long long right = 1000000000 * n;

위의 코드에서 실수를 했었다. right가 long long 형이더라도 등호 오른쪽 식은 (int)*(int)의 형태이므로 원하는대로 작동하지 않았던 것이다. 그리고 중간값을 구하는 과정을 고치는 것이 좋아보인다.

// mid = (left + right)/2;
mid = left + (right-left)/2;

경우에따라 left + right가 자료형의 최대 범위를 넘어 오버플로우를 발생시킬 수 있기 때문이다. 전혀 신경쓰지 않은 부분인데, 문제에 따라 중요한 부분이 될 수 있겠다는 생각이 들었다.

코드

// 11:11 ~ 11:43
#include <string>
#include <vector>

using namespace std;

long long solution(int n, vector<int> times) {
    long long left = 0;
    long long right = 1000000000 * (long long)n;
    long long mid, sum;
    
    while(left < right){
        mid = (left + right)/2;
        sum = 0;
        for(int time : times) sum += mid / (long long)time;
        
        if(sum >= n) right = mid;
        else left = mid + 1;
    }
    
    return right;
}

예전 코드

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

long long solution(int n, vector<int> times) {
    long long ans = 0, min, max, mid;
    long long cnt;
    sort(times.begin(), times.end());
    min = 1;
    max = times[times.size()-1] * (long long)n;
    ans = max;
    while(min < max){
        mid = (min+max)/2;
        cnt = 0;
        for(auto t : times) cnt += mid/t;
        
        if(n <= cnt){
            max = mid-1;
            ans = mid;
        }
        else min = mid + 1;
    }
    return ans;
}