코딩테스트/BOJ

[BOJ] 1202 보석 도둑 - JAVA

5월._. 2023. 6. 28.
728x90

1. 문제

 

1202번: 보석 도둑

첫째 줄에 N과 K가 주어진다. (1 ≤ N, K ≤ 300,000) 다음 N개 줄에는 각 보석의 정보 Mi와 Vi가 주어진다. (0 ≤ Mi, Vi ≤ 1,000,000) 다음 K개 줄에는 가방에 담을 수 있는 최대 무게 Ci가 주어진다. (1 ≤ Ci

www.acmicpc.net

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

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

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


2. 풀이

pq를 이용해 현재 가방에 넣을 수 있는 보석 중 가장 값어치 있는 것만 뽑아내는 방식이다.

입력 및 정렬

보석과 가방 모두 무게순으로 오름차순 정렬한다.

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(in.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());

ArrayList<int[]> jewel = new ArrayList<>();
for(int i=0;i<N;i++){
   st = new StringTokenizer(in.readLine());
   jewel.add(new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())});
}
Collections.sort(jewel,(o1, o2) -> o1[0]-o2[0]);

int[] backpack = new int[K];
for(int i=0;i<K;i++) backpack[i] = Integer.parseInt(in.readLine());
Arrays.sort(backpack);

 

탐색

가격으로 내림차순 정렬되는 pq를 만든다.

last는 pq에 넣지 않은 보석의 위치다.

가방을 무게 순으로 탐색하면서, 현재 가방에 last위치 보석을 넣을 수 있다면 pq에 넣고 last+1한다.

pq에는 현재 가방에 담을 수 있는 보석이 담겨져 있다. answer에 pq의 첫번째 보석 가격을 더한다.

 

탐색이 끝난 후에 answer을 출력한다.

long answer = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o2[1]-o1[1]);
int last = 0;
for(int i=0;i<K;i++){
   while(last < N && backpack[i] >= jewel.get(last)[0]){
      pq.offer(jewel.get(last++));
   }
   if(!pq.isEmpty()) answer += pq.poll()[1];
}

System.out.println(answer);

 

전체 코드

import java.io.*;
import java.util.*;

public class BOJ_1202_보석도둑 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      StringTokenizer st = new StringTokenizer(in.readLine());
      int N = Integer.parseInt(st.nextToken());
      int K = Integer.parseInt(st.nextToken());

      ArrayList<int[]> jewel = new ArrayList<>();
      for(int i=0;i<N;i++){
         st = new StringTokenizer(in.readLine());
         jewel.add(new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())});
      }
      Collections.sort(jewel,(o1, o2) -> o1[0]-o2[0]);

      int[] backpack = new int[K];
      for(int i=0;i<K;i++) backpack[i] = Integer.parseInt(in.readLine());
      Arrays.sort(backpack);

      long answer = 0;
      PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o2[1]-o1[1]);
      int last = 0;
      for(int i=0;i<K;i++){
         while(last < N && backpack[i] >= jewel.get(last)[0]){
            pq.offer(jewel.get(last++));
         }
         if(!pq.isEmpty()) answer += pq.poll()[1];
      }

      System.out.println(answer);
   }
}

3. 결과

pq에 보석을 모두 넣고 가능한 가방 위치를 lower_bound 찾는 방식으로 이분탐색을 진행했더니 시간초과가 났다.

이 문제는 보석 기준이 아니라 가방 기준으로 풀어야되는 문제였던 것 같다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 5557 1학년 - JAVA  (0) 2023.06.30
[BOJ] 9625 BABBA - JAVA  (0) 2023.06.29
[BOJ] 1937 욕심쟁이 판다 - JAVA  (0) 2023.06.27
[BOJ] 11049 행렬 곱셈 순서 - JAVA  (0) 2023.06.26
[BOJ] 18428 감시 피하기 - JAVA  (0) 2023.06.25

댓글