3079번: 입국심사
첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ M ≤ 1,000,000,000) 다음 N개 줄에는 각 심사대에서 심사를 하는데 걸리는 시간인 Tk가 주어진다. (1 ≤ Tk ≤ 109)
www.acmicpc.net
이분 탐색 문제다.
이분 탐색 카테고리가 없었다면 이분 탐색이라는 방법을 쓸 생각을 못 했을 것 같다. 아마 각 줄에 몇 명이 있어야하는지 알고리즘이 딱히 없었기 때문에 모든 시간을 탐색해서 확인하는 방법이 필요했을 것이다. 그 과정에서 시간은 순차적이기 때문에 이분 탐색이어야만 했다.
주어진 시간동안 각각의 줄에서 처리할 수 있는 사람의 수를 구해 그 사람의 수가 M보다 큰지 작은지 확인해 범위를 좁혀나간다. 스케줄 표를 작성하는 게 아니라 시간만 확인하면 되기 때문에 누가 어디에 들어갔는지는 굳이 신경써도 되지 않아도 됨! 과정에서 M의 최대값은 10^9, N의 최대 값은 10^5이기 때문에 이분 탐색 시 범위가 int를 초과한다. 따라서 long long타입을 써야 오류가 나지 않는다.
단 의문인 점은 계산 시간을 줄이기 위해 사람 수를 구하는 과정에서 M이 초과되면 break를 걸어줄 때 break를 걸어주지 않는다면 오류가 난다. 답과 관련된 건 아닌 것 같은데 왜 오류가 나는지 모르겠다. 아시면 답좀. 그리고 해당 문제를 찾아보다가 다른 블로그 글의 코드를 돌려봤는데 거진 전부 32%즘에서 틀렸다고 떴다. 뭔가 답이 틀려졌나..?
(++ 추가
프로그래머스에서도 같은 문제가 있어서 풀어봤다. 프로그래머스에서는 break를 걸어주지 않아도 괜찮음. 대신 주의해야할 점이 있는데 max_time이 long long type이라 M * max_time할 때 int * int 곱이 되지 않는지 확인해줘야 한다. int끼리의 곱은 int형식으로 계산 되기 때문에 long long으로 들어가더라도 int형식으로 들어간다.
다시 말해 M과 max_time의 곱이 int 범위를 넘어서면 long long으로 자동 변환되는 게 아니라 int 범위 그대로 들어가기 때문에 범위가 잘린다.
#include <iostream>
using namespace std;
typedef long long ll;
int main() {
ll N, M;
cin >> N >> M;
ll time[100001];
ll max_time = 0;
for (int i = 0; i < N; i++) {
cin >> time[i];
if (max_time < time[i]) max_time = time[i];
}
ll start = 1;
ll end = M * max_time;
while (start <= end) {
ll middle = (start + end) / 2;
ll tmp = 0;
for (int i = 0; i < N; i++){
tmp += (middle / time[i]); // i번째 창구에서 middle 시간동안 처리할 수 있는 사람의 수
if (tmp >= M)
break;
}
if (tmp >= M) end = middle - 1; // 처리할 수 있는 사람보다 많으므로 시간을 줄임
else start = middle + 1;
}
cout << start;
}
'코딩테스트' 카테고리의 다른 글
[20444] 색종이와 가위 (0) | 2024.01.13 |
---|---|
[2470] 두 용액 (1) | 2024.01.11 |
[22871] 징검다리 건너기 (2) | 2024.01.09 |
[1654] 랜선 자르기 (0) | 2024.01.07 |
[2805] 나무 자르기 (1) | 2024.01.07 |
댓글