https://www.acmicpc.net/problem/13164
안녕하세요, 이륙사입니다.
풀이
위 문제는 비용이 키 차이와 관련있다는 사실에서부터 시작하는 문제였습니다.
인접한 원생들의 키 차이를 값으로 갖는 새로운 수열을 구합니다. 그리고 그 수열의 합에서 값이 가장 큰 k-1개의 값을 빼면 그것이 정답이 됩니다. 왜냐하면 (큰 키 - 작은 키)의 값은 그 사이에 있는 원생들간 키 차이의 합과 같기 때문입니다. 그리고 아래 예시처럼 조를 k개로 나누면 k-1개의 경계가 생기며, 그 경계에 해당하는 차이 값들만 비용을 계산하는데 사용되지 않습니다. 따라서, 전체 차이의 합에서 가장 큰 k-1개를 빼주면 그것이 답이 됩니다.
예)
7, 3
1 3 5 6 10 16 19
또한, 전체 값의 합에서 가장 큰 값들을 빼주기 때문에 그리디 유형의 문제라고 할 수 있습니다.
생각 과정
- 학생 수가 최대 300,000이므로, 전부 확인해볼 순 없다.
- 비용은 조에서 가장 키가 큰 학생과 가장 작은 학생의 차이다 --> 값의 차이에 주목한다.
- 인접 원소들간 차이에 대해서도 생각해볼 수 있다.
- 가장 키가 큰 학생과 작은 학생의 키 차이는 두 학생 사이에 있는 학생들간 키 차이의 합이란 것을 발견한다.
- 조를 나누어본 결과, 비용의 합은 전체 키 차이의 합에서 가장 큰 k-1개의 값을 뺀 값이라는 것을 확인한다.
코드
import java.io.BufferedReader
import java.io.InputStreamReader
import java.util.*
import kotlin.math.sqrt
fun main() = with(BufferedReader(InputStreamReader(System.`in`))) {
val (n, k) = readLine().split(" ").map{ it.toInt() }
val st = StringTokenizer(readLine())
val gaps = IntArray(n) { st.nextToken().toInt() }
// 인접 학생간 키차이를 값으로 갖는 수열
for (i in 0 until n-1) {
gaps[i] = gaps[i+1] - gaps[i]
}
// k개로 나누면 k-1개의 경계가 생긴다
gaps.sort() // 전체에서 값이 큰 경계 k-1개를 빼기 위해 먼저 정렬한다
// 가장 큰 k-1개를 뺀 나머지를 모두 더한다
val min = (0 until (n-1)-(k-1)).sumOf { i -> gaps[i] }
print(min)
}
'Problem Solving > 백준' 카테고리의 다른 글
백준 1525번: 퍼즐 (Kotlin) (0) | 2022.01.17 |
---|---|
백준 2186번: 문자판 (Kotlin) (0) | 2022.01.16 |
백준 22862번: 가장 긴 짝수 연속한 부분 수열 (large) (Kotlin) (0) | 2022.01.14 |
백준 1697번: 숨바꼭질 (Kotlin) (0) | 2022.01.11 |
백준 1451번: 직사각형으로 나누기 (Kotlin) (0) | 2022.01.11 |