[백준 2616] - 소형기관차(Kotlin)[골드3]

2024. 4. 7. 00:09· CodingTest/Baekjoon
목차
  1. 문제
  2. 문제 풀이
  3. 전체 코드

문제

https://www.acmicpc.net/problem/2616

 

2616번: 소형기관차

첫째 줄에 기관차가 끌고 가던 객차의 수가 입력된다. 그 수는 50,000 이하이다. 둘째 줄에는 기관차가 끌고 가던 객차에 타고 있는 손님의 수가 1번 객차부터 차례로 입력된다. 한 객차에 타고 있

www.acmicpc.net

 

문제 풀이

문제를 읽고 누적합을 구해서 소형차를 배정하는 문제인 것 같았다.

문제에서 주어진 테스트케이스에 대해서 먼저 누적합에 대한 그림을 그려보았다.

처음으로 접근한 방법은 정해진 구간까지의 최대 누적합을 구하는 방법으로 접근했다.

예를 들어 50까지 접근했을때의 최댓값은 40과 50을 태운 90이다.

다음으로 10까지 접근했을때의 최댓값은 40과 50을 태운 90 vs (35+40), (50+10)중 후자의 값이었다.

구간별로 배정할 수 있는 최대의 값을 구했다.

private fun getAccumulateSum() {
for (i in 0 until k) {
sum[k - 1] += ary[i]
}
for (i in k until n) {
sum[i] = sum[i - 1] - ary[i - k] + ary[i]
}
dp[k - 1] = sum[k - 1]
for (i in k until n) {
dp[i] = max(dp[i - 1], dp[i - k] + sum[i])
}
}

 

문제에서 주어진 테스트케이스에 대해선 정답이 나왔지만, 소형차가 3대라는 점과, 연속적으로 뽑지 않을 경우도 있기 때문에 

특정테스트케이스에 대해서  통과하지 못했다.

따라서 소형차 3대에 대한 정보와 차를 배정했는지에 대한 여부를 판단해야 했기에, DP 배열을 2차원으로 접근하는 것이 맞다고 생각했다.

 

초기에 정의한 1차원 DP 배열은 다음과 같다.

dp[i] = index i까지 k개의 칸을 고려했을 때의 최대 누적합

 

수정한 2차원 DP 배열은 다음과 같다.

dp[i][j] = i번째 소형차를 j칸까지 검사했을 때의 최대 합

 

 

첫 번째 소형차에 대해서 최댓값은 (45,60)의 구간을 담는 105가 최댓값이다.

다음으로 두 번째 소형차의 구간은 첫번째 소형차의 정보를 이용해서 계산해야 한다.

두번째 소형차의 최댓값은 첫 번째에서 (40,50)을 담은 90과 (45,60)을 담은 105를 더한 195가 최대일 것이다.

다음으로 세 번째 소형차의 구간은 첫번째, 두번째 소형차의 정보를 이용해서 계산해야 한다.

세번째 소형차의 최댓값은 (35,40) + (50,10) + (45,60)인 240이 최댓값일 것이다.

 

어떻게 구할 수 있을까?

배낭 문제와 유사하게 접근하면 된다.

예를 들어 60을 마지막으로 소형차를 배정할 때, 2번째 소형차에서 60을 담지 않는 구간인 30까지의 최댓값을 이용해야 한다.

60을 담기 위해선 45,60을 이전 소형차가 배정받으면 안 된다.

즉 소형차의 배정칸 이전 구간을 확인하면 된다.

 

따라서 dp 점화식은 다음과 같다.

dp[i][j] = maxOf(dp[i-1][j], dp[i][j-1], dp[i-1][j-소형차칸] + j칸 까지의 누적합 

dp[i-1][j]와 dp[i][j-1]이 추가된 이유는 해당 칸을 배정받지 않았을 때를 의미한다.

마지막 조건은 해당 칸을 배정받았을 때를 의미한다.

 

전체 코드

class Solution {
private val br = System.`in`.bufferedReader()
private var n = 0
private var k = 0
private lateinit var ary: IntArray
private lateinit var sum: IntArray
private lateinit var dp: Array<IntArray>
fun run() {
input()
getAccumulateSum()
solve()
print(dp[3][n])
}
private fun input() {
n = br.readLine().toInt()
ary = br.readLine().split(" ").map { it.toInt() }.toIntArray()
sum = IntArray(n + 1)
dp = Array(4) { IntArray(n + 1) }
k = br.readLine().toInt()
}
private fun solve() {
for (i in 1..3) {
for (j in k..n) {
dp[i][j] = maxOf(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - k] + sum[j - 1])
}
}
}
private fun getAccumulateSum() {
for (i in 0 until k) {
sum[k - 1] += ary[i]
}
for (i in k until n) {
sum[i] = sum[i - 1] - ary[i - k] + ary[i]
}
}
}
fun main() {
val solution = Solution().run()
}
저작자표시 (새창열림)

'CodingTest > Baekjoon' 카테고리의 다른 글

[백준 1939] - 중량제한(Kotlin)[골드3]  (0) 2024.04.14
[백준 1029] - 그림 교환(Kotlin)[골드1]  (1) 2024.04.10
[백준 2482] - 색상환(Kotlin)[골드3]  (0) 2024.04.05
[백준 2252] - 줄 세우기(Kotlin)[골드3]  (0) 2024.04.02
[백준 1915] - 가장 큰 정사각형(Kotlin)[골드4]  (0) 2024.04.02
  1. 문제
  2. 문제 풀이
  3. 전체 코드
'CodingTest/Baekjoon' 카테고리의 다른 글
  • [백준 1939] - 중량제한(Kotlin)[골드3]
  • [백준 1029] - 그림 교환(Kotlin)[골드1]
  • [백준 2482] - 색상환(Kotlin)[골드3]
  • [백준 2252] - 줄 세우기(Kotlin)[골드3]
재한
재한
안녕하세요 💻
재한
짜이한
전체
오늘
어제
  • 분류 전체보기 (502)
    • Skils (116)
      • Android (50)
      • C++ (5)
      • Kotlin (36)
      • Algorithm (24)
      • Server (1)
    • CodingTest (228)
      • Programmers (45)
      • Baekjoon (183)
    • Experience (8)
      • 후기(코딩테스트,프로그램,프로젝트) (8)
    • Computer Science (70)
      • Design Pattern (2)
      • OOP (2)
      • Computer Architecture (14)
      • OS (2)
      • Software Engineering (3)
      • DataBase (8)
      • Network (39)
    • 학교 (75)
      • R프로그래밍 (26)
      • 회계와 사회생활 (17)
      • 컴퓨터학개론 (20)
      • it기술경영개론 (12)

블로그 메뉴

  • 홈
  • 태그
  • 카테고리
  • 글쓰기
  • 설정

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
재한
[백준 2616] - 소형기관차(Kotlin)[골드3]
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.