(BOJ) 1149 RGB거리

1149 RGB거리

  • 분류 : 동적계획법

문제

RGB거리에는 집이 N개 있다. 거리는 선분으로 나타낼 수 있고, 1번 집부터 N번 집이 순서대로 있다.

집은 빨강, 초록, 파랑 중 하나의 색으로 칠해야 한다.

각각의 집을 빨강, 초록, 파랑으로 칠하는 비용이 주어졌을 때, 아래 규칙을 만족하면서 모든 집을 칠하는 비용의 최솟값을 구해보자.

  • 1번 집의 색은 2번 집의 색과 같지 않아야 한다.
  • N번 집의 색은 N-1번 집의 색과 같지 않아야 한다.
  • i(2 ≤ i ≤ N-1)번 집의 색은 i-1번, i+1번 집의 색과 같지 않아야 한다.

입력

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다.

둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다.

집을 칠하는 비용은 1,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 모든 집을 칠하는 비용의 최솟값을 출력한다.

예제 입력 1

1
2
3
4
3
26 40 83
49 60 57
13 89 99

예제 출력 1

1
96

예제 입력 2

1
2
3
4
3
1 100 100
100 1 100
100 100 1

예제 출력 2

1
3

예제 입력 3

1
2
3
4
3
1 100 100
100 100 100
1 100 100

예제 출력 3

1
102

예제 입력 4

1
2
3
4
5
6
7
6
30 19 5
64 77 64
15 19 97
4 71 57
90 86 84
93 32 91

예제 출력 4

1
208

예제 입력 5

1
2
3
4
5
6
7
8
9
8
71 39 44
32 83 55
51 37 63
89 29 100
83 58 11
65 13 15
47 25 29
60 66 19

예제 출력 5

1
253

Solution

Expander
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
32
33
34
35
36
37
38
39
40
41
42
import java.util.*

private var N: Int = 0

data class RGB(
var red: Int = 0,
var green: Int = 0,
var blue: Int = 0
)


private lateinit var input: Array<RGB>

fun main() {
input()
solve()
}

private fun input() = with(Scanner(System.`in`)) {
N = nextInt() // 집의 수 N(2 ≤ N ≤ 1,000)

input = Array(N) {
RGB()
}

for (i in 0 until N) {
input[i].red = nextInt()
input[i].green = nextInt()
input[i].blue = nextInt()
}
}

private fun solve() {
for (i in 1 until N) {
input[i].red += Math.min(input[i - 1].green, input[i - 1].blue)
input[i].green += Math.min(input[i - 1].red, input[i - 1].blue)
input[i].blue += Math.min(input[i - 1].red, input[i - 1].green)
}

val result = listOf(input[N - 1].red, input[N - 1].green, input[N - 1].blue).min()
println(result)
}

Point of Thinking

  • 칠하는 색상이 연속으로 겹치면 안되므로 N+1번째 집은 N번째 집과 다른 색상의 값으로 계산해야한다.
  • 각 색상별로 점화식을 작성하면 아래와 같다.
DP[i+1].red+=min(DP[i].green,DP[i].blue)DP[i+1].green+=min(DP[i].red,DP[i].blue)DP[i+1].blue+=min(DP[i].red,DP[i].green)DP[i+1].red += min(DP[i].green, DP[i].blue) \newline DP[i+1].green += min(DP[i].red, DP[i].blue) \newline DP[i+1].blue += min(DP[i].red, DP[i].green)

  • 최종적으로 최솟값은 입력된 집의 수인 N에 해당하는 인덱스에 저장된다.
min(DP[N].red,DP[N].blue,DP[N].green)min(DP[N].red, DP[N].blue, DP[N].green)

  • 마지막 인덱스의 RGB값중 가장 작은 값을 반환하면 Accepted.

References