알고리즘 풀이/백준

[백준 2792] 보석 상자

mhko411 2021. 7. 5. 23:43
728x90

문제

보석 공장에서 보석 상자를 유치원에 기증했다. 각각의 보석은 M가지 서로 다른 색상 중 한 색상이다. 원장 선생님은 모든 보석을 N명의 학생들에게 나누어 주려고 한다. 이때, 보석을 받지 못하는 학생이 있어도 된다. 하지만, 학생은 항상 같은 색상의 보석만 가져간다.

한 아이가 너무 많은 보석을 가져가게 되면, 다른 아이들이 질투를 한다. 원장 선생님은 이런 질투심을 수치화하는데 성공했는데, 질투심은 가장 많은 보석을 가져간 학생이 가지고 있는 보석의 개수이다. 원장 선생님은 질투심이 최소가 되게 보석을 나누어 주려고 한다.

상자에 빨간 보석이 4개 (RRRR), 파란 보석이 7개 (BBBBBBB) 있었고, 이 보석을 5명의 아이들에게 나누어 주는 경우를 생각해보자. RR, RR, BB, BB, BBB로 보석을 나누어주면 질투심은 3이 되고, 이 값보다 작게 나누어 줄 수 없다.

상자 안의 보석 정보와 학생의 수가 주어졌을 때, 질투심이 최소가 되게 보석을 나누어주는 방법을 알아내는 프로그램을 작성하시오.

 

입력

첫째 줄에 아이들의 수 N과 색상의 수 M이 주어진다. (1 ≤ N ≤ 10^9, 1 ≤ M ≤ 300,000, M ≤ N)

다음 M개 줄에는 구간 [1, 109]에 포함되는 양의 정수가 하나씩 주어진다. K번째 줄에 주어지는 숫자는 K번 색상 보석의 개수이다.

 

출력

첫째 줄에 질투심의 최솟값을 출력한다.


접근

보석을 못 가져가는 학생이 있어도 된다. 이때 보석을 가져간 사람들 중 보석을 많이 가져간 사람의 개수가 질투심이 되고 이를 최소로 해야한다.

 

만약 4, 7일 때 한 명이 7 다른 한 명이 4를 가져가면 질투심은 7이된다.

따라서 한 명이 가져가는 보석의 수를 탐색하여 최소 질투심을 구하도록 한다.

각 보석의 개수를 한 사람이 가져가는 보석의 수로 나눈 것을 모두 더하면 보석을 가져간 사람의 수가 나온다.

 

이 값이 N보다 크다는 것은 N명보다 많은 사람이 보석을 가져간 것이기 때문에 한 사람이 가져가는 보석의 수를 증가시키고 반대의 경우에는 N명 이하라면 문제의 조건에 맞기 때문에 한 사람이 가져가는 보석의 수를 감소시켜본다.

 

구현

- mid는 한 사람이 가져가는 보석의 수이다.

- mid를 각각의 색에 대한 보석의 수로 나눈 몫을 total에 더하고

- total이 N보다 크다면 left값을 증가시키고

- 반대라면 right를 감소시킨다.

- 최종해는 left의 값을 출력한다. 

while left <= right:
    mid = (left+right) // 2
    total = 0
    for color in colors:
        if color % mid == 0:
            total += color//mid
        else:
            total += (color//mid) + 1
    # total이 더 크다는 것은
    # N명보다 더 많은 사람이 보석을 가져간 것
    # 그렇기 때문에 더 적게 가져가도록 하기위해 left를 증가시켜야함
    # 한 명이 가져가는 보석의 수를 늘림
    if total > N:
        left = mid + 1

    else:
        right = mid - 1

전체 코드

# 보석상자
import sys
input = sys.stdin.readline

N, M = map(int, input().split())
colors = []
for _ in range(M):
    colors.append(int(input()))

left = 1
right = max(colors)

while left <= right:
    mid = (left+right) // 2
    total = 0
    for color in colors:
        if color % mid == 0:
            total += color//mid
        else:
            total += (color//mid) + 1
    # total이 더 크다는 것은
    # N명보다 더 많은 사람이 보석을 가져간 것
    # 그렇기 때문에 더 적게 가져가도록 하기위해 left를 증가시켜야함
    # 한 명이 가져가는 보석의 수를 늘림
    if total > N:
        left = mid + 1

    else:
        right = mid - 1

print(left)

'알고리즘 풀이 > 백준' 카테고리의 다른 글

[백준 2343] 기타 레슨  (0) 2021.07.06
[백준 2613] 숫자구슬  (0) 2021.07.06
[백준 3079] 입국심사  (0) 2021.07.05
[백준 1365] 꼬인 전깃줄  (0) 2021.07.02
[백준 2352] 반도체 설계  (0) 2021.06.30