문제
https://www.acmicpc.net/problem/2343
2343번: 기타 레슨
강토는 자신의 기타 강의 동영상을 블루레이로 만들어 판매하려고 한다. 블루레이에는 총 N개의 강의가 들어가는데, 블루레이를 녹화할 때, 강의의 순서가 바뀌면 안 된다. 순서가 뒤바뀌는 경
www.acmicpc.net
풀이
이분탐색 문제이다.
mid 값을 블루레이 중 최소값으로 두고 이분탐색을 수행한다.
문제에 주어진 예제로 예를 들면,
9 3
1 2 3 4 5 6 7 8 9
mid | 16 | 17 | 18 |
구간 | [1 2 3 4 5] [6 7] [8 9] 8+9 > 16 => cnt++ |
[1 2 3 4 5] [6 7] [8 9] |
[1 2 3 4 5] [6 7] [8 9] |
cnt | 3 | 2 | 2 |
위와 같이 mid 값이 최소값 이상의 숫자라면 cnt가 M보다 작게 된다.
따라서 ask 함수에서 cnt 값이 M 이하인 경우 True를 반환하고
cnt 값이 M보다 큰 경우에는 False를 반환한 후, mid 값을 키워주기 위해 left=mid+1을 수행한다.
하지만 이 방식으로는 아래와 같은 반례를 통과하지 못한다.
7 7
5 9 6 8 7 7 5
따라서 mid 값이 강의 길이 하나보다 작다면 mid 값이 커져야 하므로 False를 리턴하도록 했다.
(블루레이의 크기가 너무 작아서 강의 한 개도 담을 수 없으므로)
탐색할 범위는 0 ~ 10^9 으로 설정하여 이분탐색을 수행한다.
코드
#include <iostream>
using namespace std;
int N, M;
int arr[100001];
bool ask(long long mid) {
int cnt = 1, sum = 0;
for (int i = 0; i < N; i++) {
if (arr[i] > mid) return false; // mid 값이 너무 작아서 강의 한 개도 담을 수 없으므로 mid 값을 증가시켜야 함.
if (sum + arr[i] > mid) {
cnt++;
sum = 0;
}
sum += arr[i];
}
return cnt <= M;
}
int main() {
cin >> N >> M;
for (int i = 0; i < N; i++) {
cin >> arr[i];
}
long long right = 1000000000; // 강의 수(10^5)와 강의 길이(10^4)의 최대값의 곱
long long left = 0;
long long ans, mid;
while (left < right) {
mid = (left + right) / 2;
if (ask(mid)) {
ans = mid;
right = mid;
} else left = mid + 1;
}
cout << ans;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
백준 2470 - 두 용액 (C++) (0) | 2024.03.19 |
---|---|
누적 합 (0) | 2024.03.11 |
백준 1753 - 최단경로(C++) (1) | 2023.11.29 |
백준 11404 - 플로이드(C++) (1) | 2023.11.28 |
Problem 1600 - 말이 되고픈 원숭이(C++) (1) | 2023.11.24 |