백준 1202 보석 도둑 java

Nov 23, 2025
백준 1202 보석 도둑 java

1. 문제에 대하여 📦

보석은 무게와 가격이 주어지고, 가방은 무게가 주어진다. 가방에는 자신의 무게보다 작은 보석만 담을 수 있으며, 한 번에 하나의 보석밖에 담지 못한다. 일련의 보석과 일련의 가방이 있을 때, 가방에 담은 보석의 최대 가격은 얼마인가?

2. 코드가 나오기까지 🛠️

KEY WORD: 그리디 알고리즘
푸는 방법은 다음과 같다.
  1. 가방은 무게 오름차순으로 정렬, 보석은 무게 오름차순, 무게 동등 시, 가격 내림차순 정렬
  1. 보석을 담을 가방을 무게가 가장 낮은 것부터 집는다.
  1. 해당 가방에 담을 수 있는 (보석 무게 < 가방 무게)인 모든 보석을 후보군으로 보낸다.
    (후보군은 가격 내림차순 정렬)
  1. 후보군에서 가장 가치가 큰 것을 집는다.
  1. 가방을 모두 채울 떄까지 위의 과정 반복
image.png
이렇게 있다고 쳤을 때, 제일 작은 가방인 2용량 가방부터 집는다. 2보다 무게가 작은 보석은(1,64)(2,99)이다. 이 둘을 후보군에 넣는다. 후보군은 가격 내림차순임으로 (2,99)가 선두로 올 것이다.
이 중 (2,99)를 가방에 넣는다.
image.png
다음 가방은 용량이 6이다. 이보다 작은 남아있는 보석들을 모두 후보지에 넣는다.
image.png
이 중 제일 큰(1,64)를 넣는다.
image.png
10에 대해서도 같은 과정을 반복하면 모든 가방에 최대치를 넣을 수 있다.
image.png

(1) 보석, 가방 둘 다 무게 오름차순으로 문제를 푸는 이유

후순위 계산인 가방에 가능한 한 선택지를 많이 열어주기 위해서 이다.
가방의 무게가 클수록 선택지가 넓고, 작을수록 좁은 것을 볼 수 있다. 이는 반대로 선택지가 좁은 가방에 최대값을 먼저 고려하면, 비교적 선택지가 넓은 가방에서는 담지 않아도 되는 후보군을 추릴 수 있어, 최대값 산정이 더 쉽다.
또한 무게 내림차순 해서 구하면, 최대 가치를 담지 못하고, 가치 내림차순해서 구하면, 무게가 작은 가방에 담을 수 있었던 보석을 큰 데 담아서 무게가 작은 가방을 활용하지 못하는 경우의 수도 생긴다.

(1) 시간복잡도 분석 ⏳

  1. 보석을 모두 우선순위 큐에 넣는다. -> O(N x logN)
  1. 보석을 한 번 돌며 후보지에 넣는다. -> O(N)
  1. 새로운 값을 후보지에 넣을 때마다 재정렬한다. -> O(logN)
위의 과정에서 1번 따로, 2,3번 같이 일어남. 따라서 최악의 시간복잡도는 O(N x logN) 이다.

3. 코드 🌐

(1) SUDO CODE 💬

// 위에 적어서 생략

(2) JAVA CODE ☕

import java.util.*; import java.io.*; // b 17255 N으로 만들기 public class Main { static class Jewel { int w; int v; public Jewel (int w, int v){ this.w = w; this.v = v; } } static int N, K; static int [] bag; static PriorityQueue<Jewel> pq = new PriorityQueue<>((a,b) -> { if(a.w == b.w) return b.v - a.v; return a.w - b.w; }); public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()); bag = new int [K]; for(int i = 0; i< N; i++){ st = new StringTokenizer(br.readLine()); pq.add(new Jewel(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()))); } for(int i = 0; i < K; i++){ bag[i] = Integer.parseInt(br.readLine()); } Arrays.sort(bag); long acc = 0; PriorityQueue<Jewel> candidate = new PriorityQueue<>((a,b) -> (b.v - a.v)); for(int i = 0; i < K; i++){ int now_backpack = bag[i]; while (!pq.isEmpty() && pq.peek().w <= now_backpack){ candidate.add(pq.poll()); } if(!candidate.isEmpty()) acc += candidate.poll().v; } System.out.printf("%d", acc); } }

4. 트러블 슈팅 or 배운 점📝

무게 오름차순으로 정렬했다 생각하고 구현은 무게 내림차순으로 하는 행동으로 한 번 틀렸다. 코드 항상 제대로 확인하자.