본문 바로가기
백준

[1654] 랜선 자르기

by kmyobin 2022. 10. 1.


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

 

1654번: 랜선 자르기

첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그

www.acmicpc.net

 

 

요즘 문제 이해하는 시간도 오래 걸린다 ..

K = 4, N = 11, 갖고 있는 랜선의 길이가 차례로

802
743
457
539

라면!

 

이미 있는 4개의 랜선을 동일한 크기로 다 쪼개면 랜선의 개수가 N개 이상이 되어야 함.


// 802 : 200 200 200 200 2
// 743 : 200 200 200 143
// 457 : 200 200 57
// 539 : 200 200 139

// 200개 총 11 개

 

랜선의 길이를 200으로 했을 때 11개,  즉 N개의 랜선을 만들 수 있다.

그리고 200이 랜선 길이의 최댓값이기 때문이 답이 되는 것이다.

 

 

그럼 랜선 길이의 범위를 알아보자.

근데 나와있다. 2^31-1(2,147,483,647)보다 작거나 같은 자연수(0은 포함X)이다.

근데 다 탐색하면 시간이 너무 아까우므로 입력받은 랜선들의 길이 중 최댓값랜선 길이의 최대 범위로 설정하자

그러면 우리는 1 ~ max(A)에서 자를 수 있는 랜선 최대 길이를 구하면 된다.

 

 

구하는 과정은 쉬운데, 자료형 범위 설정에서 조금 헤맸다.

이분 탐색으로 구했는데, key를 설정하는 과정에서 overflow가 발생했다.

long long int key = (start + end) / 2; // start랑 end 더해서 int의 범위를 넘어갈 수 있으므로 long long

start와 end는 int로 설정했는데 key를 long long int 으로 설정해서 이미 (start + end)에서 overflow가 났다.

그러므로 start와 end도 long long 으로 자료형을 맞춰줘야 한다.

 

 

나머지는 주석으로 자세히 적어놓았다.

#include <iostream>
using namespace std;

int N, K;
int A[1000000];
int maximum = -1;
// 802 : 200 200 200 200 2
// 743 : 200 200 200 143
// 457 : 200 200 57
// 539 : 200 200 139

// 200개 총 11 개


// 랜선 길이의 범위는? 0 ~ 2^31 -> 0 ~ max(A)


void BinarySearch(long long int start, long long int end) { // 안 하면 key 부분에서 오버플로우가 나는 듯
	if (start > end) return;

	long long int key = (start + end) / 2; // start랑 end 더해서 int의 범위를 넘어갈 수 있으므로 long long

	long long int cnt = 0;
	bool is_success = false;
	for (int i = 0; i < K; i++) {
		cnt += A[i] / key; // 랜선의 길이가 최대 2^31-1이므로 key가 최소일 때 cnt에서 overflow 발생 가능. 그러므로 cnt가 long long
		if (cnt >= N) { // N개 이상으로 많이 만들면
			is_success = true;
			break; // 나가
		}
	}

	if (is_success) {
		maximum = (key > maximum) ? key : maximum; // 최댓값 갱신
		BinarySearch(key + 1, end); // 더 최대 길이 있는지 key보다 큰 범위에서 찾아봄
	}
	else { 
		BinarySearch(start, key - 1);
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> K >> N; // 이미 K개가 있는데 N개의 랜선이 필요함

	int maxi = -1;
	for (int i = 0; i < K; i++)
	{
		cin >> A[i];
		maxi = (A[i] > maxi) ? A[i] : maxi;
	}

	BinarySearch(1, maxi); // 1부터 maxi까지 탐색

	cout << maximum;
}

'백준' 카테고리의 다른 글

[3190] 뱀  (0) 2022.10.05
[11664] 선분과 점  (0) 2022.10.02
[2805] 나무 자르기  (0) 2022.09.30
[2343] 기타 레슨  (0) 2022.09.28
[2512] 예산  (0) 2022.09.27

댓글