알고리즘/백준
2805 나무 자르기
흰싸라기
2022. 3. 23. 10:26
백준 2805번 나무자르기 : https://www.acmicpc.net/problem/2805
2805번: 나무 자르기
첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000) 둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M보
www.acmicpc.net
이 문제는 이분탐색으로 풀 수 있는 문제다
이분 탐색 참고 -> https://wh514.tistory.com/20
[코드 작성 전]
우선, 높이를 입력받으며 미리 나무 중 가장 높은 높이(hmax)를 저장한다.
탐색 범위를 0 ~ hmax로 설정하고 이분 탐색을 진행한다.
- 중간 값(cutter)를 절단기 설정 높이로 가정하고 가져갈 수 있는 나무의 높이를 for문으로 계산한다
- 계산한 값을 M과 대소비교 후 결과에 따라 탐색범위 수정
탐색 후, 나온 값은 M과 가장 가까운 값이므로 M보다 작을 수도 있다. 따라서, 작은 경우에는 따로 처리가 필요하다.
[문제 풀이]
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m;
cin >> n >> m;
int* tree = new int[n];
int cutter = 0;
int hmin = 0;
int hmax = 0;
for (int i = 0; i < n; i++) {
int k;
cin >> k;
tree[i] = k;
hmax = max(hmax, k);
}
ll tm = 0;
while (hmax >= hmin) { // hmax < hmin 이면 탈출
cutter = (hmin + hmax) / 2;
tm = 0;
for (int i = 0; i < n; i++) { // 가져갈 수 있는 나무 높이 계산
if (tree[i] > cutter) {
tm += tree[i] - cutter;
}
}
//탐색
if (m > tm) {
hmax = cutter - 1;
}
else if (m < tm) {
hmin = cutter + 1;
}
else break;
}
if (tm < m) cutter--; // 문제의 M보다 작으면
cout << cutter;
return 0;
}
int *tree = new tree | 나무 높이를 저장하는 배열 |
int cutter, hmax, hmin | cutter : 절단기 설정 높이 hmax : 탐색 범위 중 가장 큰 값 - 처음 값은 tree 배열 값 중 가장 큰 값 : 입력 시 설정 hmin : 탐색 범위 중 가장 작은 값 |
ll tm | 탐색중 가져갈 수 있는 나무 값 저장 빛 비교를 위해 사용 - int가 아닌 long long 사용 |
while(hmax>=hmin) | ① 탐색 범위 중간 값 cutter에 저장 ② 현재 cutter값 기준으로 가져갈 수 있는 나무 높이 계산 ③ 현재 가져갈 수 있는 높이와 M과 대소비교 후 hmax,hmin 값 조정 ④ tm == m 또는 hmax < hmin 인 경우 루프 탈출 |
if(tm<m) cutter--; | 가장 가까운 경우이므로, 작으면 cutter--를 통해 값이 커지도록 수정 (다만, 탐색 중 tm이 m보다 큰 경우에만 답을 수정하면 따로 처리가 필요없다.) |
[comment]
우선 이전에 풀었던 이분탐색을 정리하다가 발견해서 푼거라 이분탐색인걸 알고 시작한게 아쉽다,, 대신 그만큼 빨리 풀긴했다..
과거에는 어렵다 생각했었는데 이번에 풀면서 미리 코드를 어떻게 짤지 생각하고 푸니까 쉽게 풀려서 문제풀 때 미리 코드 정리하는 것의 중요성을 깨달아서 좋았다.