Post

BOJ 1202 보석 도둑

BOJ 1202 보석 도둑

https://www.acmicpc.net/problem/1202

문제

세계적인 도둑 상덕이는 보석점을 털기로 결심했다.

상덕이가 털 보석점에는 보석이 총 N개 있다. 각 보석은 무게 $M_i$와 가격 $V_i$를 가지고 있다. 상덕이는 가방을 K개 가지고 있고, 각 가방에 담을 수 있는 최대 무게는 $C_i$이다. 가방에는 최대 한 개의 보석만 넣을 수 있다.

상덕이가 훔칠 수 있는 보석의 최대 가격을 구하는 프로그램을 작성하시오.


입력

첫째 줄에 N과 K가 주어진다. $(1 ≤ N, K ≤ 300,000)$

다음 N개 줄에는 각 보석의 정보 $M_i$와 $V_i$가 주어진다. $(0 ≤ M_i, V_i ≤ 1,000,000)$

다음 K개 줄에는 가방에 담을 수 있는 최대 무게 $C_i$가 주어진다. $(1 ≤ C_i ≤ 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

힌트

두 번째 예제의 경우 첫 번째 보석을 두 번째 가방에, 세 번째 보석을 첫 번째 가방에 넣으면 된다.


코드

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
    static class Jewel implements Comparable<Jewel> {
        int weight, price;

        public Jewel(int weight, int price) {
            this.weight = weight;
            this.price = price;
        }

        @Override
        public int compareTo(Jewel o) {
            return weight - o.weight;
        }
    }

    /**
     * 1. 보석과 가방을 낮은 무게 순으로 뽑을 수 있도록 각각 우선순위 큐에 넣는다
     * 2. 가장 낮은 무게의 가방에 담을 수 있는 보석을 검사해 가장 높은 가치의 보석을 담는다
     * 2-1. 담을 수 있는 가장 높은 가치의 보석을 검사할 때, 탈락한 보석의 가치는 또 다른 우선순위 큐에 넣는다
     * 3. 그 다음 순서의 가방에 담을 수 있는 가장 높은 가치의 보석을 검사하고,
     *    그 보석의 가치와 탈락한 보석의 가치 우선순위 큐에서 peek한 가치 중 큰 것을 가장 높은 가치의 보석으로 결정
     * 4. 3번을 반복
     * 5. 모든 보석을 검사 후 가방에 넣고도 가방이 남는다면, 탈락한 보석의 가치 우선순위 큐에서 차례로 poll 해서 가방을 채움
     */
    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()), K = Integer.parseInt(st.nextToken());
        PriorityQueue<Jewel> jewels = new PriorityQueue<>();
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            jewels.offer(new Jewel(
                    Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())
            ));
        }

        PriorityQueue<Integer> bags = new PriorityQueue<>();
        for (int i = 0; i < K; i++) bags.offer(Integer.parseInt(br.readLine()));

        long answer = 0;
        PriorityQueue<Integer> leftJewels = new PriorityQueue<>(Collections.reverseOrder());
        while (!bags.isEmpty() && !jewels.isEmpty()) {
            int maxWeight = bags.poll(), maxPrice = 0;
            while (!jewels.isEmpty() && jewels.peek().weight <= maxWeight) {
                Jewel check = jewels.poll();
                if(maxPrice < check.price) {
                    if (maxPrice > 0) leftJewels.offer(maxPrice);
                    maxPrice = check.price;
                } else leftJewels.offer(check.price);
            }
            if(!leftJewels.isEmpty() && leftJewels.peek() > maxPrice) {
                answer += leftJewels.poll();
                leftJewels.offer(maxPrice);
            } else answer += maxPrice;
        }

        while (!bags.isEmpty() && !leftJewels.isEmpty()) {
            bags.poll();
            answer += leftJewels.poll();
        }

        System.out.println(answer);
    }
}
This post is licensed under CC BY 4.0 by the author.