티스토리 뷰
문제 설명
https://www.acmicpc.net/problem/1202
세계적인 도둑 상덕이는 보석점을 털기로 결심했다.
상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 Mi와 가격 Vi를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 Ci이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.
상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000)
다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000)
다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci ≤ 100,000,000)
모든 숫자는 양의 정수이다.
출력
첫째 줄에 상덕이가 훔칠 수 있는 보석 가격의 합의 최댓값을 출력한다.
예제 입력 1
2 1
5 10
100 100
11
예제 출력 1
10
예제 입력 2
3 2
1 65
5 23
2 99
10
2
예제 출력 2
164
힌트
두 번째 예제의 경우 첫 번째 보석을 두 번째 가방에, 세 번째 보석을 첫 번째 가방에 넣으면 된다.
문제 요약) 보석마다 무게와 가격이 있고, 가방에는 무게 제한이 있습니다. 하나의 가방에 하나의 보석만 담을 수 있을 때 담을 수 있는 보석의 최대 가격을 구해라.
풀이 과정
보석 무게는 적을수록 좋은데, 가격은 높을수록 좋습니다.
무게 제한 값이 작은 가방부터 하나씩 확인하는데, 그 가방에 넣을 수 있는 모든 보석들의 가격을 최대힙 구조로 저장합니다. 최대 가격을 뽑아야 하니까요.
그 가방에 넣을 수 없는 보석 A가 뜨면, 최대힙에서 보석의 최대 가격을 꺼내고 answer에 저장합니다. 이로써 현재 가방에 가능한 최대 가격의 보석을 담게 되는 겁니다.
그리고 다음 가방을 확인합니다. 앞의 가방이 넣을 수 없었던 A를 이 가방도 못 넣는다면, 이 가방도 최대힙에서 보석의 최대 가격을 꺼내고 answer에 저장합니다. 가방은 무게 제한이 작은 것부터 확인하고 있으니, 최대힙에 존재하는 모든 보석은 이 가방에도 담을 수 있는 보석들이 되기 때문이죠.
그리고 그 다음 가방을 확인하는데, 앞의 가방들이 담지 못한 A 보석을 담을 수 있는 가방이라면 A의 가격을 최대힙에 추가합니다.
이를 모든 가방을 확인할 때까지 계속 반복합니다.
최대힙에는 현재 가방에 담을 수 있는 ‘후보 보석들의 가격’이 최대힙 구조로 저장될 것입니다.
파이썬 heapq 자료구조를 사용할 때 알아야 할 점은
- 기본적으로 최소힙으로 구성됩니다.
- 그래서 최대힙으로 구성하려면 값에 -를 붙이면 됩니다.
- 오름차순으로 출력되지 않습니다.
- heapq는 리스트 전체를 정렬하는 게 아니라, 내부적으로 완전이진트리 구조에서 최소값이 루트(인덱스 0)에 있도록 유지합니다.
- 그래서 리스트 형태로 보면 이상하게 보일 수 있지만, heap[0]이 항상 최소라는 점은 자료구조적으로 보장됩니다.
정답 코드
import sys
import heapq as hq
input = sys.stdin.readline
N, K = map(int, input().split())
# 보석 정보를 (보석 무게, 보석 가격) 튜플 형태로 저장할 리스트
# 보석 무게를 기준으로 최소힙이 될 것
jewels = []
# 가방 무게 제한을 담을 리스트
bag_limits = []
answer = 0
# M 값을 기준으로 최소힙 jewels 구성
for _ in range(N):
M, V = map(int, input().split())
hq.heappush(jewels, (M, V))
# 가방 무게 제한 리스트 구성하고
for _ in range(K):
bag_limits.append(int(input().strip()))
# 오름차순 정렬
bag_limits.sort()
# 보석 가격을 최대힙 구조로 저장할 리스트 생성
jewel_values = []
# 무게 제한 작은 가방부터 확인
for limit in bag_limits:
# 담을 보석이 아직 있고, 가장 가벼운 보석이 현재 가방에 들어가면
while jewels and limit >= jewels[0][0]:
# 가장 가벼운 보석을 jewels에서 빼고
# 해당 보석의 무게값을 - 붙여서 (최대힙으로 만들기 위해)
# jewel_values에 넣는다
hq.heappush(jewel_values, -hq.heappop(jewels)[1])
# 최대힙에 가격이 남아 있으면
if jewel_values:
# 보석의 최대 가격을 answer에 더한다
# 원래 값으로 돌리기 위해 -를 붙인다
answer += -hq.heappop(jewel_values)
print(answer)
가방의 무게 배열과 보석 정보 배열은 무게 값을 기준으로 작은 값부터 얻을 수 있도록 구성하고, 보석의 가격만 저장하는 배열을 따로 만들어 최대힙으로 구성하여 큰 값부터 얻을 수 있도록 하는 것이 핵심이었습니다.
이상입니다.
'Algorithm' 카테고리의 다른 글
SWEA 1206번: View (D3) - Python 풀이 (0) | 2025.04.17 |
---|---|
SWEA 1859번: 백만 장자 프로젝트 (D2) - Python 풀이 (0) | 2025.04.17 |
프로그래머스 Lv.2: 다리를 지나는 트럭 - Python 풀이 (0) | 2025.04.15 |
프로그래머스 Lv.2: 프로세스 - Python 풀이 (0) | 2025.04.14 |
백준 2812번: 크게 만들기 (G3) - Python 풀이 (0) | 2025.04.11 |
- Total
- Today
- Yesterday
- 다익스트라
- 투포인터
- 코딩테스트
- 우선순위큐
- 백준
- 구현
- Swift
- Programmers
- Baekjoon
- 힙
- 다이나믹프로그래밍
- 정렬
- 큐
- dp
- SQL
- 프로그래머스
- 자료구조
- 코테
- Python
- swea
- MySQL
- Deque
- ios앱개발
- 코테준비
- 이분탐색
- ios
- 알고리즘
- Swift로백준풀기
- 그리디
- 스택
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |