문제
https://www.acmicpc.net/problem/16401
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
문제 요약
길이가 L인 막대 과자 N개가 있을 때, M명의 모든 조카들에게 같은 길이의 막대 과자를 나누어 줄 수 있다.
이 때 나누어 줄 수 있는 가장 긴 막대 과자의 길이를 출력한다.
+ 막대 과자는 길이와 상관없이 여러 조각으로 나누어 질 수 있지만, 과자를 하나로 합칠 수는 없다.
코드
M, N = map(int, input().split())
# M은 조카 수, N은 과자 수
arr = list(map(int, input().split()))
# 과자의 길이를 저장하는 리스트
start = 1
end = max(arr) # 가장 긴 과자 길이
# 이진 탐색의 시작 범위와 끝 범위
res = 0 # 나누어 줄 수 있는 막대 과자 최대 길이
while start <= end:
mid = (start + end) // 2
# 검사할 길이 mid
total = 0
# 길이 mid로 나누었을 때 조카들이 받을 수 있는 과자 개수
for x in arr:
if x >= mid:
# 길이가 mid 이상인 과자가 있다면
total += (x // mid)
# 과자 한 개를 길이가 mid인 과자 여러 개로 나눌 수 있기 때문
if total >= M:
# mid 길이로 나누어줄 수 있는 과자가 조카 수 이상이라면
start = mid + 1 # 이진 탐색 범위를 좁혀 더 긴 길이도 가능한지 검사
res = mid
else:
end = mid - 1 # 이진 탐색 범위를 좁혀 더 작은 길이는 가능한지 검사
print(res)
코드 설명
1. 길이가 1일 때부터 입력 받은 막대 과자들 중 가장 긴 길이까지 조건에 맞는 값을 갱신하며 이진 탐색을 진행한다. (범위: start ~ end)
2. 탐색 범위의 중간 값인 mid는 조카들 수만큼 길이가 mid인 과자 여러개 나누어 줄 수 있는지 검사할 길이이다.
3. 과자 한 개를 여러 개로 나눌 수 있으므로 입력 받은 막대 과자 중 mid로 여러번 나눌 수 있는 과자가 있다면, 그만큼 조카들이 받을 수 있는 과자 개수는 증가한다.
4. 나누어 줄 수 있는 과자 수와 조카들 수를 비교하여 이진 탐색 범위를 조정한다.
5. start가 end보다 커지면 탐색을 종료한다.
'Algorithm Problems > 이진 탐색' 카테고리의 다른 글
[백준/Python] 2110번: 공유기 설치 (2) | 2023.11.05 |
---|---|
[백준/Python] 2805번: 나무 자르기 (1) | 2023.11.03 |
[백준/python] 17951번: 흩날리는 시험지 속에서 내 평점이 느껴진거야 (2) | 2023.08.21 |
[백준/python] 2343번: 기타 레슨 (3) | 2023.08.21 |
[백준/python] 7795번: 먹을 것인가 먹힐 것인가 (2) | 2023.07.28 |