
가. 접근 방법
1) 가방에 물건들을 효율적으로 "어떻게" 넣어야 보석 가격 합의 최댓값을 구할 수 있을까? 만약 내가 보석을 훔친다면, 가벼운 무게부터 훔칠 것이다. 왜냐하면 가벼운 무게는 나중에 널찍한 가방(담을 수 있는 공간이 큰)에도 담을 수 있기 때문이다. 하지만 반대로 무거운 물건은 나중에 담으면 담기 어려워지는 상황이 생길 것이다.
위와 같은 상황을 고려해 필자는 가방 사이즈를 작은 순으로 나열하고 해당 가방에 물건들을 넣을 생각이다. 필자는 여기서 한번 더 생각한다. "작은 가방을 선택했으니 낮은 무게부터 골라야 하지 않겠냐고".
이 문제는 가방에 담을 수 있는 물건의 목록 들을 구하는데, 작은 것부터 시작하자는 것이다.
2) 따라서 작은 가방부터 넣을 물건들을 추린 뒤, 그 중에서 가치가 높은 물건을 선택하면 될것이고, 주의할 점은 추리는 공간을 모든 가방이 공유한다는 것이다.
이 전에 추려놨던 물건들은 다음 가방에서도 "무조건" 가져갈 수 있기 때문이다. 왜냐하면 가방 용량 순으로 내침차순 정렬했기에, 이전의 가방보다 현재의 가방의 용량이 무조건 높을 것이기 때문이다.
나. 사용할 알고리즘 및 자료구조 선택
1) 그리디
각 가방에 넣는 보석이 현재시점에서 가장 높은 가치를 가지고 있는 것이기 때문이다.
2) 우선순위 큐
가장 높은 가치를 가진 보석을 선택할 때, 힙으로 정렬된 자료구조를 사용하면 빠르다. 그리고 입력할 때
바로 정렬된다.
가. 물건 정보 2차원 배열을 무게를 기준으로 오름차순 정렬
나. 가방 무게 정보 배열을 오름차순 정렬
다. 가방 정보 배열을 순회해서 넣을 수 있는 무게를 큐에 넣고
라. 다 넣었으면, 가장 높은 가치 Poll하여 결과값에 더함.
참고로 우선순위 큐를 아래와 같이 내림차순으로 설정하여야 한다.
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
가. NullPtr 에러
res값 우선순위 큐에서 poll해서 갱신할 때, empty check안해서 생긴 문제. 따라서 다음과 같이 수정
if (!pq.isEmpty()) { res += pq.poll(); }
import java.io.*;
import java.util.*;
public class P1202 {
public static void main(String args[]) throws IOException {
// N : 총 보석 개수
// K : 상덕이의 가방 개수
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int K = Integer.parseInt(st.nextToken());
int[][] jwe = new int[N][2];
int[] bag = new int[K];
long res = 0;
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
jwe[i][0] = Integer.parseInt(st.nextToken());
jwe[i][1] = Integer.parseInt(st.nextToken());
}
Arrays.sort(jwe, (a, b) -> a[0] - b[0]);
for (int i = 0; i < K; i++) {
bag[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(bag);
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
int j = 0;
for (int i = 0; i < K; i++) {
while (j < N && jwe[j][0] <= bag[i]) {
pq.add(jwe[j][1]);
j++;
}
if (!pq.isEmpty()) {
res += pq.poll();
}
}
bw.write(res + "\n");
bw.flush();
bw.close();
}
}
가. Arrays.sort의 Big O
이다.
나. Buffer로 IO 처리
Input
1 2
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(st.nextToken() + "\n");
bw.write(st.nextToken());
bw.flush();
bw.close();
>>
1
2
다. while문은 if문의 확장버전
상당히 어려웠고, 동시에 여러개를 생각하려니 힘이 들었다. 계속 풀어봐야 할 거 같다.