백준/실랜디, 골랜디

[백준] 나무 자르기(2805) *

2zreal 2024. 12. 26. 19:03

나무를 위에서부터 잘라서 적어도 M미터의 나무를 집으로 가져가야 할 때 높이의 최댓값을 구하는 문제이다.

간단하게 위에서부터 모두 확인하면 문제를 해결할 수 있어 보이지만... 이 문제의 입력값을 잘 보아야 한다.

 

나무의 길이(20억까지)

나무의 수(100만까지)

 

for문으로 일일이 전부 다 확인하면 무조건 시간초과가 발생할 것이다.

그렇다면 이 문제는 어떻게 해결해야 하는가??

이분탐색을 이용해서 해결하면 된다.

이분탐색이란 L와 R 그리고 mid의 값을 가지고 왼쪽으로 갈지 오른쪽으로 갈지 확인하는 것이다.

 

#include <iostream>
#include <algorithm>

using namespace std;

long long arr[1000001];

int main(void)
{
	long long N = 0;
	long long M = 0;
	long long sum = 0;

	cin >> N >> M;

	for (int i = 0; i < N; i++)
	{
		cin >> arr[i];
	}

	long long start = 0;
	long long end = 1000000000;
	long long mid = 0;

	long long result = 0;

	while (start <= end)
	{
		mid = (start + end) / 2;
		sum = 0;

		for (int i = 0; i < N; i++)
		{
			if (arr[i] > mid)
			{
				sum = sum + arr[i]-mid;
			}
		}

		if (sum == M)
		{
			result = mid;
			break;
		}
		else if (sum > M)//클때만 원하기 때문에 여기서만 result를 갱신
		{
			start = mid + 1;
			if (result < mid)
			{
				result = mid;
			}
			
		}
		else
		{
			end = mid - 1;
		}

	}

	cout << result;

	return 0;
}

 

문제풀이방법

1.Start가 End보다 작거나 같을 때까지 while문을 반복한다.

2.mid의 값을 구하고 이 값을 이용해서 가져갈 수 있는 나무를 저장한다.

3. 만약 가져갈 수 있는 나무와 원하는 값이 딱 맞아떨어지면 바로 break 한다.

4. 딱 맞아떨어지지 않고 가져갈 수 있는 나무의 값이 M보다 더 크면 start의 값을 mid의 한 칸 오른쪽으로 옮긴다.(그래야 다음번에 가져갈 수 있는 나무의 값이 작아지기 때문)

5. 딱 맞아떨어지지 않고 가져갈 수 있는 나무의 값이 M보다 더 작으면 end의 값을 mid의 한 칸 왼쪽으로 옮긴다.(그래야 다음번에 가져갈 수 있는 나무의 값이 커지기 때문.) 결국 높이의 최댓값을 찾는 문제임.

 

기본적으로 이분탐색 문제는 정렬이 필요로 하는데 이 문제의 경우에는 정렬을 하지 않고도 풀 수 있다.

'백준 > 실랜디, 골랜디' 카테고리의 다른 글

[백준] 쉬운 최단거리(14940)  (0) 2024.12.29
[백준] C++ RGB거리(1149)  (0) 2024.12.28
[백준] C++ 좌표압축(18870)  (0) 2024.12.27
[백준] C++ AC(5430)  (1) 2024.12.27
[백준] 스택 수열(1874)  (2) 2024.12.26