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

 

1202번: 보석 도둑

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

www.acmicpc.net

 

 

보석도둑 문제입니다.

핵심 아이디어는, 가방에 담을 수 있는 가장 비싼 보석을 담자! (Greedy)입니다.

다만 고려해야할 상황이 몇 개 있습니다.

 

우선 큰 가방에 비싼 보석을 담는다면 작은 가방에 아무것도 담지 못하는 비효율적인 상황이 생길 수 있습니다.

그러니 작은 가방을 먼저 채우는것이 좋습니다.

 

둘째, 가방의 갯수가 30만개, 보석의 가격이 100만까지 가능하므로 최대 3000억의 값이 정답으로 나올 수 있습니다.

정답을 long (C계열의 경우 longlong) 타입으로 선언해 주어야 오버플로우가 발생하지 않을 것 같습니다.

 

셋째, 보석과 가방의 갯수를 자세히 보시면... 둘 사이에는 부등호가 없습니다.

즉 가방이 보석보다 많을 수도 있다는 뜻입니다.

저는 이 부분을 놓쳐서 NullPoint Exception을 한 번 보았네요.

 

 

풀이로 들어가겠습니다.

작은 가방부터 넣을 수 있는 최대의 보석을 담습니다. 

저는 그래서 보석과 가방의 정보를 모두 받고, 둘을 모두 오름차순으로 정렬해 주었습니다.

 

그리고 정렬된 가장 가벼운 가방부터 담을 수 있는 가장 비싼 보석을 찾는데,

보석의 정보가 이미 정렬되어 있으므로 한 번 순회하며 자기가 담을 수 있는 보석까지만 PriorityQueue에 넣었습니다.

PriorityQueue의 Comparator를 람다식으로 설정해서 가치가 높은 보석이 위로 올라오게 했으므로 이 PriorityQueue안에는 내가 담을 수 있고 가장 비싼 보석이 위에 존재하게 됩니다.

PriorityQueue에서 보석 하나를 꺼내어 담는 처리를 하고 (정답에 누적합하고) 다음 크기의 가방에 대해 같은 작업을 반복하면 됩니다. 

 

좀 더 최적화된 방법이 있을것 같은데 나중에 생각나면 포스팅을 업데이트 하도록 하겠습니다!

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main{
	static StringTokenizer st;

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		st = new StringTokenizer(br.readLine());
		int N = Integer.parseInt(st.nextToken());
		int K = Integer.parseInt(st.nextToken());

		PriorityQueue<int[]> pqueue = new PriorityQueue<int[]>((e1, e2) -> {
			return e2[1] - e1[1];
		});
		int[][] jewels = new int[N][2];
		int[] bags = new int[K];

		for (int n = 0; n < N; n++) {
			st = new StringTokenizer(br.readLine());
			jewels[n][0] = Integer.parseInt(st.nextToken());
			jewels[n][1] = Integer.parseInt(st.nextToken());
		}

		for (int k = 0; k < K; k++) {
			bags[k] = Integer.parseInt(br.readLine());
		}

		Arrays.sort(jewels, (e1, e2) -> {
			return e1[0] - e2[0];
		});
		Arrays.sort(bags);

		int index = 0;
		long answer = 0;

		for (int k = 0; k < K; k++) {
			int nowBag = bags[k];

			while (index < N) {
				if (jewels[index][0] <= nowBag) {
					pqueue.add(jewels[index].clone());
					index++;
				} else {
					break;
				}
			}
			if(!pqueue.isEmpty()) {
				answer += pqueue.poll()[1];
			}
		}

		System.out.println(answer);
	}
}

 

 

 

 

728x90

+ Recent posts