랜선 자르기

08 September 2019

문제 : https://www.acmicpc.net/problem/1654

이번은 흔히 parametric search라고도 부르는, 이분 탐색을 응용하여 최솟값이나 최댓값을 찾는 테크닉을 배우는 문제를 풀어보도록 하겠습니다.

#include<stdio.h>

static long long *arr;
static int N;
static int target;
static long long max = 0;

long long binarySearch();

int main(void) {

	scanf("%d %d", &N, &target);

	arr = new long long[N];

	for (int i = 0; i < N; i++)
	{
		scanf("%lld", &arr[i]);
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}

	printf("%lld", binarySearch());

	return 0;
}

bool isAvailable(int val) {
	int sum = 0;
	for (int i = 0; i < N; i++)
	{
		sum += arr[i] / val;
	}

	if (sum >= target)
	{
		return true;
	}
	return false;
}

long long binarySearch() {
	long long start = 0;
	long long end = max;

	while (end >= start)
	{

		long long mid = (start + end) / 2;

		if (end - start <= 1)
		{
			if (isAvailable(end))
			{
				return end;
			}
			return start;
		}

		if (isAvailable(mid))
		{
			start = mid;
		}
		else {
			end = mid - 1;
		}
	}
	return 0;
}
가지고 있는 랜선으로 만들 수 있는 최대 랜선의 길이를 찾는 문제입니다.
갯수에 상관없이 가장 작은 길이는 0이고, 가장 큰 길이는 가지고 있는 랜선의 길이의 최대값입니다.
여기서 최소값과 최대값 사이에서 이분 탐색을 통해, 주어진 조건을 만족하는, 즉 잘라서 해당 갯수가 나오는 값을 찾으면 됩니다.
해당 갯수가 나오면 해당 값을 start로 정하고, 안 나오면 end를 mid-1로 정하여 점점 범위를 줄여주고
start와 end의 차가 1일때, end와 start 값을 비교하여 가능한 것 중 큰 값을 return해주도록 합니다.