Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 네트워크모델
- 코딩공부
- BAEKJOON
- Java
- 스프링 부트와 AWS로 혼자 구현하는 웹 서비스
- 스프링
- cs공부
- 코딩테스트
- DP
- 개발자
- 네트워크
- 정렬
- 개발공부
- 전송계층
- 서버
- 다이내믹프로그래밍
- 백준
- Lan
- SSAFY
- Spring
- Dynamic Programming
- TCP
- 프로토콜
- 싸피
- IP
- 알고리즘
- 알고리즘공부
- 자바
- 구현
- 클라이언트
Archives
- Today
- Total
오늘 하루, develop
백준 1202번 - 보석 도둑 (java) 본문
💡 문제 링크
https://www.acmicpc.net/problem/1202
💡 아이디어
지난번 Comparator 관련 글을 작성한 후 연습이 하고 싶어 관련 문제를 찾아서 풀었다.
온전히 스스로의 힘으로는 못하고 블로그를 참고했다.🥹
1번 아이디어 : 이중 for문
- 가방 리스트와 보석 리스트를 만들고 가방은 오름차순, 보석은 내림차순으로 정렬한다.
- 높은 가격의 보석부터 보석이 들어갈 수 있는 가방 중 가장 작은(무게 기준) 가방을 찾는다.
- 이중 for문을 활용하면 300,000 * 300,000 이므로 시간 초과가 뜰 것이다.
2번 아이디어 : 이분 탐색
- 가방 리스트와 보석 리스트를 만들고 가방은 오름차순, 보석은 내림차순으로 정렬한다.
- 높은 가격의 보석부터 보석이 들어갈 수 있는 가방 중 가장 작은(무게 기준) 가방을 찾는다.
- 여기까지는 1번 아이디어와 동일하다. 시간복잡도를 낮추기 위해 이분 탐색(lower-bound)를 활용하는 방안을 생각했다.
- 이분 탐색의 시간 복잡도는 O(logN) 이므로 300,000 * log300,000 = 약 160만 이므로 시간 초과가 나지 않을 것이라고 생각했다.
- 그러나 시간 초과가 떴다.
- 문제는 이미 사용한 가방을 사용할 수 없다는 점이었다.
- 보석이 들어갈 수 있는 가방 중 가장 작은 가방을 찾더라도 이미 보석이 담겨 있는 가방이면 그보다 큰 다른 가방을 찾아야 하는데 여기서 결국 터지는 것 같았다. (최악의 경우 O(N*K))
- 이 아이디어는 무게 기준으로 가장 작은 가방 탐색까지는 가능했지만, 이미 사용한 가방을 거르는 데 한계가 있다.
- boolean 변수를 쓰든, 리스트나 배열에서 값을 빼든 최악의 경우 O(N)이 O(K)에 곱해지기 때문이다.
3번 아이디어 : 우선순위 큐
- 우선순위 큐를 활용한다는 것은 블로그를 참고했다.
- 우선순위 큐는 값 추출(poll) 시간복잡도가 O(logN)이므로 이미 사용한 가방을 제거하고 정렬하는 시간복잡도가 작은 편이다.
알고리즘은 아래와 같다.
- 보석과 가방 모두 무게를 기준으로 오름차순 정렬한다.
- 우선순위 큐를 생성한다. (가격을 기준으로 내림차순 정렬)
- 가방 배열을 하나씩 보면서
- 가방이 감당할 수 있는 무게보다 가벼운 보석을 모두 우선순위 큐에 넣는다.
- poll한 보석의 가격을 정답 변수에 추가한다. (가장 비싼 보석이 가장 앞에 있을 것이므로)
- 위 2개 단계를 반복하되 새로운 가방에 대해 탐색할 때마다 보석을 처음부터 탐색하지는 않는다.
- 이미 넣은 보석은 다음 가방에 무조건 들어갈 수 있기 때문이다 (가방과 보석 모두 오름차순 되어 있다는 것을 기억하자)
- 이 때문에 시간복잡도도 이득을 보게 된다. O(K+NlogN)
- 큐에 넣을 때마다 정렬되므로 N*logN이 더해지는 것
💡 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class BOJ_G2_1202_보석도둑_sol {
public static int N, K;
public static Jewel[] jewels;
public static int[] bags;
public static long maxV;
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()); //가방 개수
jewels = new Jewel[N];
bags = new int[K];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
jewels[i] = new Jewel(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()));
}
for (int i = 0; i < K; i++) {
bags[i] = Integer.parseInt(br.readLine());
}
//===================== 입력 완료
//보석 무게를 기준으로 오름차순 정렬
Arrays.sort(jewels, new Comparator<Jewel>() {
@Override
public int compare(Jewel o1, Jewel o2) {
if (o1.M < o2.M) {
return -1;
} else if (o1.M > o2.M) {
return 1;
}
return 0;
}
});
//가방 무게를 기준으로 오름차순 정렬
Arrays.sort(bags);
//가격 기준으로 내림차순하는 우선순위 큐
PriorityQueue<Jewel> queue = new PriorityQueue<>(new Comparator<Jewel>() {
@Override
public int compare(Jewel o1, Jewel o2) {
if (o2.V < o1.V) {
return -1;
} else if (o2.V > o1.V) {
return 1;
}
return 0; // o2.V == o1.V
}
});
int index = 0;
for (int i = 0; i < K; i++) {
// 현재 가방에 넣을 수 있는 보석을 모두 큐에 넣음
// 가방과 보석 모두 무게 기준으로 오름차순되어 있기 때문에 새로운 가방에 넣을 보석을 처음부터 탐색하지 않아도 됨
// (index 변수가 for문 밖에서 선언된 이유)
// 이미 넣은 보석은 다음 가방에 무조건 들어갈 수 있기 때문
// 따라서 시간복잡도도 이득을 보게 됨 O(K*N)가 아닌 O(K+NlogN). 큐에 넣을 때마다 정렬되므로 N*logN이 더해짐
while (index < N && bags[i] >= jewels[index].M) {
queue.offer(jewels[index]);
index++;
}
//현재 가방에 넣을 수 있는 보석 중 가장 비싼 보석을 꺼냄
if (!queue.isEmpty()) {
maxV += queue.poll().V;
}
}
System.out.println(maxV);
}
public static class Jewel {
int M; //무게
int V; //가격
Jewel(int M, int V) {
this.M = M;
this.V = V;
}
}
}
'알고리즘' 카테고리의 다른 글
백준 1939번 - 중량제한 (java) (3) | 2024.07.24 |
---|---|
백준 16768번 - Mooyo Mooyo (java) (0) | 2024.07.19 |
자바 Comparator 간단 정리 (feat. 정렬) (0) | 2024.07.11 |
백준 14719번 - 빗물 (java) (0) | 2024.07.11 |
백준 5052번 - 전화번호 목록(java) (0) | 2024.07.10 |