문제
사탕을 좋아하는 아기 석환은, 집에 N개의 사탕이 들어있는 자루를 들여놓았다. 자루에는 두 가지 종류의 사탕이 있는데, 작은 사탕은 3g의 무게를 가지고, 큰 사탕은 5g의 무게를 가진다. 똑똑한 아기 석환은 자루에 있는 모든 사탕에 대해서, 그 사탕의 당도 si 를 계산해 놓았다. si 는 양의 정수로, si 가 클수록 사탕은 달콤하다.
shake! 2019 대회에 참가하기 위해 짐을 싸고 있는 아기 석환은, 달콤한 사탕을 최대한 많이 담아가서 대회 도중 당분을 보충하려고 한다. 하지만, 연약한 아기 석환은 가방에 최대 wg (w그램) 의 사탕만을 담을 수 있다. 아기 석환이 이 조건을 만족하면서 사탕을 담았을 때, 담아간 사탕의 당도의 합은 최대 얼마가 될 수 있을까?
입력
첫 번째 줄에 사탕의 개수 N(1 ≤ N ≤ 250,000), 무게 제한 w(0 ≤ w ≤ 5N)가 주어진다.
이후 N개의 줄에 각 사탕의 종류 ti, 당도 si가 주어진다. (t_i ∈ {3,5}, 1 ≤ si ≤ 109)
출력
아기 석환이 조건을 만족하면서 담아갈 수 있는 사탕의 당도의 최대 합을 출력하라.
풀이 과정
먼저 5g 무게의 사탕을 당도가 높은 순서대로 가방에 담을 수 있을 만큼 그리디하게 전부 다 담고, 5g 무게의 사탕을 한 개씩 빼면서 3g 무게의 사탕을 당도가 높은 순서대로 가방에 담으면서, 담아갈 수 있는 사탕의 당도의 최대 합을 구한다.
사탕을 한 개씩 빼고 한 개씩 집어넣는 과정은 시간 초과를 유발할 수 있으므로, 누적 합 테크닉을 이용하여 다량의 사탕을 담거나 빼는 과정을 한 번에 수행하여 풀이했다.
import sys
input = sys.stdin.readline
n, w = map(int, input().rstrip().split())
candy3 = []
candy5 = []
for _ in range(n):
t, s = map(int, input().rstrip().split())
if t == 3: candy3.append(s)
else: candy5.append(s)
candy3.sort(reverse=True)
candy5.sort(reverse=True)
candy3_sum = [0]
candy5_sum = [0]
for i in candy3: candy3_sum.append(candy3_sum[-1] + i)
for i in candy5: candy5_sum.append(candy5_sum[-1] + i)
# 일단 먼저 5개를 다 넣어 놓고. ( 부족한 건 3개로 채우고 )
# 5개 사탕을 1개씩 빼면서 3개 계속 채우면서 확인하기
max_result = 0
last_w = w
result = 0
now_candy5 = min(len(candy5), last_w // 5)
result += candy5_sum[now_candy5]
last_w -= now_candy5 * 5
now_candy3 = min(len(candy3), last_w // 3)
result += candy3_sum[now_candy3]
last_w -= now_candy3 * 3
max_result = result
size = now_candy5
for i in range(size):
result -= candy5[now_candy5 - 1]
now_candy5 -= 1
last_w += 5
go_candy3 = min(len(candy3) - now_candy3, last_w // 3)
result += candy3_sum[now_candy3 + go_candy3] - candy3_sum[now_candy3]
last_w -= go_candy3 * 3
now_candy3 += go_candy3
max_result = max(max_result, result)
print(max_result)
'-- 예전 기록 > BOJ' 카테고리의 다른 글
[ BOJ ] 20127 : Y-수열 ( GOLD 5 ) / Python (0) | 2024.02.01 |
---|---|
[ BOJ ] 5547 : 일루미네이션 ( GOLD 4 ) / Python (0) | 2024.02.01 |
[ BOJ ] 17779 : 게리맨더링 2 ( GOLD 3 ) / Python (0) | 2024.01.31 |
[ BOJ ] 1038 : 감소하는 수 ( GOLD 5 ) / Python (0) | 2024.01.30 |
[ BOJ ] 6603 : 로또 ( SILVER 2 ) / Python (1) | 2024.01.29 |