https://www.acmicpc.net/problem/2805
2805번: 나무 자르기
첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000) 둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M보
www.acmicpc.net
나무를 자르는 길이에 대해 이분 탐색을 실행한다. 이 때 절단기에 설정할 수 있는 높이의 최솟값은 0이고, 나무 높이의 최댓값 W에 대해 절단기의 높이가 W 이상일 경우 얻는 나무토막의 길이는 0이므로, 이분 탐색의 범위를 [0, W]로 정한다.
#include <iostream>
using namespace std;
typedef long long ll;
#define MAX_N 1000000
// N: 나무의 수, M: 원하는 나무토막의 총 길이, wood[i]: 각 나무의 길이
int N, M, wood[MAX_N];
// 나무를 높이 mid만큼 자른 뒤 얻은 나무토막의 총 길이
ll cut_wood(int mid) {
ll sum = 0;
for (auto w : wood) sum += (w > mid) ? (w - mid) : 0;
return sum;
}
int main() {
// 입출력 속도 향상
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
// min, max: 이진 탐색에 필요한 범위
int min = 0, mid, max = 1;
// 문제의 조건을 입력받으면서 이분 탐색의 범위를 조정
cin >> N >> M;
for (int i = 0; i < N; i++) {
cin >> wood[i];
// 이분 탐색의 최댓값을 나무의 최댓값으로 조정
max = max > wood[i] ? max : wood[i];
}
mid = (min + max) / 2;
// 최적의 절단기 높이를 이분 탐색을 이용해 찾는다
while (min <= max) {
// 각 나무토막을 길이 mid만큼 잘랐을 때
// 나무토막의 길이가 M 이상이라면 mid보다 큰 값에 대해,
// 그렇지 않다면 mid보다 작은 값에 대해 탐색
if (cut_wood(mid) >= M) min = mid + 1;
else max = mid - 1;
// mid 갱신
mid = (min + max) / 2;
}
// 이진탐색 결과를 출력
cout << mid << '\n';
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
2869번: 달팽이는 올라가고 싶다 (0) | 2021.12.20 |
---|---|
2839번: 설탕 배달 (0) | 2021.12.20 |
2798번: 블랙잭 (0) | 2021.12.20 |
2785번: 체인 (0) | 2021.12.17 |
2775번: 부녀회장이 될테야 (0) | 2021.12.17 |