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
힌트
두 번째 예제의 경우 첫 번째 보석을 두 번째 가방에, 세 번째 보석을 첫 번째 가방에 넣으면 된다.
정답
import java.util.*;
import java.io.*;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken()); // 보석 개수
int K = Integer.parseInt(st.nextToken()); // 가방 개수
// 보석(무게 오름차순 정렬 후 가격 내림차순 정렬)
List<Pair> jewels = new ArrayList<>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
int M = Integer.parseInt(st.nextToken()); // 보석 무게
int V = Integer.parseInt(st.nextToken()); // 보석 가격
jewels.add(new Pair(M, V));
}
Collections.sort(jewels, Comparator.comparingInt((Pair p) -> p.x)); // 무게 오름차순 정렬
// 가방 무게 배열 입력 및 정렬 (가방도 작은 것부터 처리)
int[] bags = new int[K];
for (int i = 0; i < K; i++) {
bags[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(bags);
// 우선순위 큐: 가격이 높은 순으로 저장
PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
long sum = 0;
int index = 0;
for (int i = 0; i < K; i++) {
while (index < N && jewels.get(index).x <= bags[i]) {
pq.add(jewels.get(index).y);
index++;
}
if (!pq.isEmpty()) {
sum += pq.poll();
}
}
System.out.println(sum);
}
static class Pair {
int x, y; // 무게, 가격
Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
}
코드 설명
정렬
Arrays.sort()는 배열로 정렬하지 않아도
PriorityQueue는 자동으로 정렬된 상태를 유지하기 때문에, 위의 Comparator를 넣으면 삽입 시 정렬이 적용된다.
for (int i = 0; i < K; i++) { // 각 가방에 대해
while (index < N && jewels.get(index).x <= C[i]) { // 현재 가방에 넣을 수 있는 보석을 추가
pq.add(jewels.get(index).y); // 가격을 우선순위 큐에 추가
index++; // 다음 보석으로 이동
}
if (!pq.isEmpty()) {
sum += pq.poll(); // 가장 비싼 보석 선택
}
}
while 역할: 현재 가방(C[i])에 넣을 수 있는 보석을 모두 pq에 추가
index 역할: while 내부에서 index++가 없으면, 가방마다 보석을 처음부터 탐색해야
실행 과정
• 보석을 무게 오름차순 정렬하면, 작은 가방부터 차례로 보석을 추가하는 과정에서 이전 가방에서 넣은 보석을 다시 탐색할 필요가 없음.
• PQ는 가격 내림차순 유지하므로, 가장 비싼 보석을 빠르게 꺼낼 수 있음.
예제2 정렬 후
보석 리스트 (무게 오름차순):
(2, 99), (1, 65), (5, 23)
가방 리스트 (무게 오름차순):
2, 10
1. 첫 번째 가방 (무게 2)
• 무게 ≤ 2인 보석들 PQ에 추가
→ (1, 65), (2, 99) 추가
→ PQ 상태: [99, 65] (가격 내림차순 자동 정렬)
• 가장 비싼 보석(99) 선택 → sum = 99
2. 두 번째 가방 (무게 10)
• 무게 ≤ 10인 추가 가능 보석 PQ에 추가
→ (5, 23) 추가
→ PQ 상태: [65, 23]
• 가장 비싼 보석(65) 선택 → sum = 99 + 65 = 164
'코딩테스트 > 백준' 카테고리의 다른 글
[Gold V][JAVA] 12865번: 평범한 배낭 (0) | 2025.03.13 |
---|---|
[Gold V][JAVA] 16928번: 뱀과 사다리 게임 (0) | 2025.03.12 |
[Silver IV][JAVA] 2217번:로프 (1) | 2025.03.11 |
[Gold IV][JAVA] 17114번: 미세먼지 안녕! (0) | 2025.03.10 |
[Silver V][JAVA] 1417번:국회의원선거 (1) | 2025.02.17 |