본문 바로가기
Algorithm/BOJ

[BOJ]2805번: 나무 자르기 (c++)

by HBGB 2020. 7. 8.

https://www.acmicpc.net/problem/2805

 

2805번: 나무 자르기

문제 상근이는 나무 M미터가 필요하다. 근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고,

www.acmicpc.net

 

이분 탐색

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// limit높으로 자르고 남은 길이 합 구하기
long long get_cut_off_sum(vector<int> &trees, long long limit)
{
	long long left = 0;
	for (int tree : trees)
	{
		if (tree - limit > 0)
		{
			left += tree - limit;
		}
	}
	return left;
}

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	// 입력
	int N, M;
	cin >> N >> M;
	vector<int> trees(N);
	int max_tree = 0;
	for (int i = 0; i < N; ++i)
	{
		cin >> trees[i];
		if (max_tree < trees[i])
		{
			max_tree = trees[i];
		}
	}

	// 이분탐색
	long long answer = 0;
	long long left = 0;
	long long right = max_tree;
	while (left <= right)
	{
		long long mid = (left + right) / 2;
		long long sum = get_cut_off_sum(trees, mid);

		// 자른 합이 M보다 크거나 같다면 더 높이 자를 수 있는지 확인한다
		if (sum >= M)
		{
			// 자를 수 있는 최대 높이 갱신
			answer = max(mid, answer);
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}

	// 출력
	cout << answer;

	return 0;
}

 

 

랜선자르기 문제와 비슷한 유형이다.

 

나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다.
(1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

나무의 높이의 합은 항상 M을 넘기 때문에, 상근이는 집에 필요한 나무를 항상 가져갈 수 있다.

마찬가지로 자료형의 크기를 주의해야 한다.

 

 

이분탐색으로 단순히 값을 찾는 것이 아니라,

찾아진 값을 기준으로 또 다른 조건을 충족하는 답을 찾을 때에는

재귀함수보다는 반복문을 이용한 이분탐색이 더 간편한 것 같다.

 

'Algorithm > BOJ' 카테고리의 다른 글

[BOJ]1780번: 종이의 개수 (c++)  (0) 2020.07.08
[BOJ]2110번: 공유기 설치 (c++)  (0) 2020.07.08
[BOJ]1654번: 랜선 자르기 (c++)  (0) 2020.07.08
[BOJ]11728번: 배열 합치기 (c++)  (0) 2020.07.07
[BOJ]10816번: 숫자 카드 2 (c++)  (0) 2020.07.07

댓글