Post

[백준] 17404. RGB거리 2(Python, 파이썬)

백준 온라인의 문제 풀이입니다.

📖 [백준] 17404. RGB거리 2

시간 제한메모리 제한난이도
0.5초128 MB골드 4

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

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

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

✔️ 입력

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나 같은 자연수이다.

✔️ 출력

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

✔️ 입력 출력 예시

입력출력
3
26 40 83
49 60 57
13 89 99
110
3
1 100 100
100 1 100
100 100 1
3
3
1 100 100
100 100 100
1 100 100
201
6
30 19 5
64 77 64
15 19 97
4 71 57
90 86 84
93 32 91
208
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
253

🗒️ 내 풀이

dp[i][k]를 i번 째 집에서 k번 째 색깔(빨강, 초록, 파랑)을 칠했을 때 i번 째 집까지 색깔을 칠한 비용의 최솟값이라고 하자. 이때 첫번째, 두번째 조건을 제외하고 세번째 조건(i(2 ≤ i ≤ N-1)번 집의 색은 i-1, i+1번 집의 색과 같지 않아야 한다.)만 고려하면, i - 1번 째의 k번 째 색깔을 칠하지 않았을 때의 최솟값에 해당 위치의 색깔 비용을 더하면 최솟값을 얻을 수 있다. 따라서 점화식은 아래와 같다.

\[\begin{align} dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + data[i][0]\\ dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + data[i][1]\\ dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + data[i][2]\\ \end{align}\]

여기서 첫번째, 두번째 조건을 고려해보자. 첫번째 집이 각 빨강, 초록, 파랑을 칠하는 경우를 따로따로 생각해보면 된다. 첫번째 집이 빨강을 칠했다면, n번째 집에서 초록, 파랑을 칠했을 경우 중 최솟값을 구하면 된다. 이렇게 총 3번 해서 최솟값을 구해주면 된다. 따라서 이를 구현하면 아래의 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
input = sys.stdin.readline
INF = 1e6
n = int(input())
data = [list(map(int, input().split())) for _ in range(n)]

result = INF
for k in range(3):
    dp = [[0] * 3 for _ in range(n)]
    
    dp[0][k] = data[0][k]
    dp[0][k - 1] = INF
    dp[0][k - 2] = INF
    for i in range(1, n):
        dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + data[i][0]
        dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + data[i][1]
        dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + data[i][2]
    result = min(result, min(dp[-1][k - 1], dp[-1][k - 2]))

print(result)

MinionsGIF

This post is licensed under CC BY 4.0 by the author.

[백준] 13398. 연속합 2(Python, 파이썬)

[백준] 1697. 숨바꼭질(Python, 파이썬)