https://www.acmicpc.net/problem/1826
마을까지의 거리 L, 현재 연료의 양 P와 각각 (거리, 연료량)값을 가진 주유소들이 주어진다.
마을에 도착할 수 있도록 방문할 주유소의 최소 수를 출력하는 문제이다.
전형적인 그리디 문제라고 생각해서, 금방 알고리즘을 구상하였다.
내 생각에 핵심 아이디어는 이동 가능 최대 거리였다.
최초 이동 가능 최대 거리는 시작 연료량인 P이고, 만약 주유소에서 연료를 넣는다면 연료값만큼 최대 거리를 증가시킨다.
4
4 4
5 2
11 5
15 10
25 10
위 예시를 따라가며 어떻게 진행하는지 알아보자.
최초 상태는 위와 같다. 최초 연료가 10이므로 처음 maxDistance는 10이다.
따라서 도달 가능한 주유소들 중 가장 연료를 많이 채워주는 (PQ에서 뽑은) 첫 번째 주유소에서 연료를 채우고 maxDistance를 14로 만든다.
그러면 세 번째 주유소까지 도달 가능하므로, 세 번째 주유소의 연료량인 5를 PQ에 넣는다.
fun main(args: Array<String>): Unit = with(System.`in`.bufferedReader()) {
val N = readLine().toInt()
// 거리 오름차순 정렬
val stations = Array(N){
val (d, f) = readLine().split(' ').map{it.toInt()}
Station(d, f)
}.sortedWith{s1, s2 -> s1.distance - s2.distance}
val (L, P) = readLine().split(' ').map{it.toInt()}
// 도달 가능한 주유소들의 연료 충전량 중 가장 많은 것 반환
val pq = PriorityQueue<Int>(reverseOrder())
var idx = 0
var maxDistance = P
var answer = 0
while(idx < stations.size){
if(maxDistance >= L) // 현재 상태로 마을 도착이 가능하면
break
// 마을 도착 불가능한 경우
val next = stations[idx]
if(maxDistance >= next.distance) { // 현재 상태로 다음 주유소에 도달 가능하면
pq.offer(next.fuel)
idx++
}else{ // 현재 상태로 다음 주유소 도달 불가능하면
val most = pq.poll() ?: break // 다음 주유소까지 못가는데 충전할 주유소가 남아있지 않으면 break
maxDistance += most // 도달 가능한 주유소들 중 연료 많은 주유소에서 충전
answer++
}
}
// 모든 주유소 순회 후, 마을 도착 못했을 경우
// 남은 주유소들 중 연료량 많은 순으로 하나씩 방문하며 maxDistance 늘림
while(maxDistance < L && pq.isNotEmpty()){
maxDistance += pq.poll()
answer++
}
// 모든 주유소에서 충전해도 L에 닿지 못하면 -1
print(if(maxDistance < L) -1 else answer)
}
data class Station(
val distance: Int,
val fuel: Int
)