본문 바로가기
📊알고리즘/BOJ

BOJ 16401 - 과자 나눠주기

by meteorfish 2024. 4. 13.
728x90

16401번: 과자 나눠주기 (acmicpc.net)

 

16401번: 과자 나눠주기

첫째 줄에 조카의 수 M (1 ≤ M ≤ 1,000,000), 과자의 수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 과자 N개의 길이 L1, L2, ..., LN이 공백으로 구분되어 주어진다. 과자의 길이는 (1 ≤ L1, L2, ..., LN ≤ 1,

www.acmicpc.net

 

접근 방법

가장 길게 과자를 N명에게 나눠주는 문제이다.

이때 핵심이 과자를 부러뜨리면 다시 합칠 수 없다는 것이다.

 

예제 1을 보자.

 

1 2 3 4 5 6 7 8 9 10에서 3명에게 가장 긴 과자를 주려면

8 , 9 , 10을 선택하여 9와 10을 각각 1, 2 만큼 부러뜨려 8로 맞춰 주면된다.

 

예제 2번의 경우 한 번더 생각해봐야한다.

 

10 10 15를 3명에게 나눠주려면 어떻게 해야할까?

 

10 10 7 8 로 나누 후, 가장 낮은 길이인 7로 맞춰 주면된다.

 

과자는 얼마의 길이든지 부실 수 있기 때문에, 우리는 과자를 n개로 나눠야한다.

이때 무엇을 기준으로 n개로 맞출 것인가라고 할때, 과자의 길이를 중심으로 맞추면된다.

 

이게 무슨 소리이냐면

만약 과자의 길이가 7일 때, N개로 나눌 수 없다면 과자의 길이는 1~6까지 중 하나이다.

반대로, 과자의 길이가 7일 때, N개보다 많거나 같게 나눌 수 있다면, 답은 7~ 이다.

 

어디서 많이 본 것이 아닌가? 바로 이분탐색이다.

 

이를 이분 탐색을 이용해 매우 빠르게 해결할 수 있다.

 

코드

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<map>

#define MAX_NUM 1000001

using namespace std;

int n, m;
int res;
vector<int> snack;


int main() {
	cin.tie(NULL); ios_base::sync_with_stdio(false);
	cin >> n >> m;

	int maxi = 0;
	for (int i = 0; i < m; i++) {
		int tmp;
		cin >> tmp;
		snack.push_back(tmp);
		maxi = max(maxi, tmp);
	}
	
	int l = 1, r = maxi;
	while (l <= r) {
		int mid = (l + r) / 2;
		int tmp = 0;
		
		for (int i = 0; i < m; i++) {
			tmp += snack[i] / mid;
		}

		if (tmp >= n) {
			l = mid + 1;
			res = mid;
		}
		else {
			r = mid - 1;
		}
	}

	cout << res;
}

이분 탐색으로 해결할 수 있다는 것을 파악하는데 꽤 많은 시간이 걸렸다..

이런 류의 이분탐색 문제도 있다는 것을 명심하자...

728x90

'📊알고리즘 > BOJ' 카테고리의 다른 글

BOJ 18869 - 멀티버스 II  (0) 2024.04.15
BOJ 2295 - 세 수의 합  (0) 2024.04.13
BOJ 2252 - 줄 세우기  (0) 2024.04.06
BOJ 144999 - 주사위 굴리기  (0) 2024.04.01
BOJ 13335 - 트럭  (0) 2024.03.31