코딩테스트/Java
[programmers/java] 카운트 다운 - Dijkstra, PriorityQueue
zyin
2025. 6. 21. 22:55
1. 문제 개요
- url : https://school.programmers.co.kr/learn/courses/30/lessons/131129#
"카운트다운"은 주어진 점수 target을 최소한의 다트 수로 정확히 0점으로 만드는 다트 게임이다. 각 다트는 다음과 같은 점수를 획득할 수 있다.
- 불(BULL): 50점
- 싱글(SINGLE): 1~20점
- 더블(DOUBLE): 2~40점 (2배)
- 트리플(TRIPLE): 3~60점 (3배)
조건은 다음과 같다.
- 가능한 한 최소한의 다트 수로 0점을 만드는 것이 우선이다.
- 동률일 경우 싱글 또는 불을 더 많이 던진 방법이 우선이다.
2. 해결 전략
본 문제는 상태 전이 기반 최적화 문제이며, 우선순위 큐를 이용해 가장 우선순위가 높은 상태부터 탐색하는 방식으로 풀이할 수 있다. 이를 위해 remain (남은 점수), round (던진 다트 수), single (싱글/불 던진 수)를 상태로 구성하여 최소 비용 탐색을 수행한다.
우선순위 큐에는 다음 우선순위가 적용된다.
- 던진 다트 수가 적을수록 우선
- 다트 수가 같을 경우 싱글 또는 불을 더 많이 던진 경우 우선
3. 전체 소스 코드
import java.util.*;
class Solution {
public int[] solution(int target) {
PriorityQueue<Item> pq = new PriorityQueue<>();
Set<Integer> visited = new HashSet<>();
pq.offer(new Item(target, 0, 0));
while (!pq.isEmpty()) {
Item cur = pq.poll();
if (cur.remain == 0) {
return new int[]{cur.round, cur.single};
}
if (visited.contains(cur.remain)) continue;
visited.add(cur.remain);
// 불(BULL, 50점)
if (cur.remain >= 50) {
pq.offer(new Item(cur.remain - 50, cur.round + 1, cur.single + 1));
}
// 1~20점에 대해 싱글, 더블, 트리플
for (int i = 1; i <= 20; i++) {
if (cur.remain >= i) {
pq.offer(new Item(cur.remain - i, cur.round + 1, cur.single + 1)); // 싱글
}
if (cur.remain >= i * 2) {
pq.offer(new Item(cur.remain - i * 2, cur.round + 1, cur.single)); // 더블
}
if (cur.remain >= i * 3) {
pq.offer(new Item(cur.remain - i * 3, cur.round + 1, cur.single)); // 트리플
}
}
}
return new int[]{}; // 도달 불가한 경우 (존재하지 않음)
}
class Item implements Comparable<Item> {
int remain;
int round;
int single;
public Item(int remain, int round, int single) {
this.remain = remain;
this.round = round;
this.single = single;
}
@Override
public int compareTo(Item o) {
if (this.round != o.round) return this.round - o.round;
return o.single - this.single; // 싱글/불 더 많이 던진 경우 우선
}
}
}
4. 핵심 구현 설명
4.1 우선순위 큐
- PriorityQueue<Item>을 사용하여 가장 유리한 상태부터 처리한다.
- 내부적으로 compareTo 기준에 따라 정렬된다.
관련 메서드 설명
함수 | 설명 |
pq.offer(element) | 요소를 큐에 삽입하고 내부 우선순위에 따라 정렬한다. |
pq.poll() | 우선순위가 가장 높은 요소를 제거하고 반환한다. |
pq.isEmpty() | 큐가 비어있는지를 판단한다. |
4.2 상태 클래스: Item
@Override
public int compareTo(Item o) {
if (this.round != o.round) return this.round - o.round;
return o.single - this.single;
}
반환값 | 의미 |
음수 (< 0) | this 객체가 o 객체보다 앞에(우선) 와야 함 |
0 | this 객체와 o 객체는 동등한 우선순위를 가짐 |
양수 (> 0) | this 객체가 o 객체보다 뒤에(후순위) 와야 함 |