알고리즘 :: 큰돌 :: Chapter 6 - 이분탐색 :: 백준 14627번 파닭파닭

Embedded June·2023년 9월 3일
0
post-thumbnail

문제

문제 링크

해설

  • 문제를 요약하면,
    • ' S개의 파를 길이 L의 파로 자를 때 C개의 덩어리를 만들 수 있는가? '
    • ' 이때 L의 최댓값을 구하고, 정답은 요소의 합 - L을 출력하시오. ' 입니다.
  • L은 최대 10억, S는 최대 100만이기 때문에 일반적인 방법으로는 100% 시간초과가 날 것임을 알 수 있습니다. 그러므로 이분탐색을 이용해서 최적화문제를 결정문제로 변경합시다.
    • 즉, '파의 길이가 mid일 때, C개의 덩어리를 만들 수 있는가? Yes or No? '로 문제를 변경합니다.
  • i번째 파를 길이 L인 파로 몇 개의 덩어리를 만들 수 있을까요? floor((double)파 / 파의 길이)로 계산할 수 있습니다. 왜냐하면, 소수점은 버려야 할 테니까요.
  • 이렇게 최대 길이를 구했다면 전체 길이의 합에서 최대 길이 × C를 뺀 값을 출력하면 정답입니다.

주의할 점

  • 이분탐색의 범위 중 오른쪽 범위의 포인터를 담당하는 high 변수의 초깃값에 대한 이야기를 하고 싶습니다.
  • S와 C가 1부터 시작되는데, 둘 다 1인 경우에는 그냥 입력받은 파를 파닭에 넣으면 됩니다.
  • 하지만, 저희의 이분탐색 알고리즘은 가장 처음에 mid 부터 시작되기 때문에, S와 C가 1인 경우를 처리할 수 없어서 실패가 뜰 것입니다.
  • 따라서, high를 입력받은 S개의 파 중 최댓값의 2배로 설정해서 mid가 S개의 파 중 최댓값부터 시작할 수 있도록 처리합니다. 이렇게 하면 예외를 처리할 수 있습니다.

코드

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int S, C, A[1'000'001]; 
ll low, high, mid, len, sum;

bool isAvailable() {
	ll cnt = 0;
	for (int i = 0; i < S; ++i) cnt += floor((double)A[i] / mid);
	return cnt < C;
}

int main() {
	cin.tie(0)->sync_with_stdio(0);
	
	cin >> S >> C;
	for (int i = 0; i < S; ++i) {
		cin >> A[i];
		sum += A[i];
		if (high < A[i]) high = A[i];
	}
	high <<= 1;
	while (low <= high) {
		mid = low + (high - low) / 2;
		if (isAvailable()) high = mid - 1;
		else low = mid + 1, len = mid;
	}
	cout << sum - len * C;
}

소스코드 링크

결과

profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글