Programming/백준
[골드 4] 백준 17404 - RGB거리 2 (파이썬)
pental
2025. 6. 30. 10:19
https://www.acmicpc.net/problem/17404
풀이
이 문제는 다이나믹 프로그래밍을 사용해서 최소 비용을 계싼하는 문제이다.
각 집은 R(0), G(1), B(2) 중 하나의 색으로만 칠해야 하며, 이웃한 집은 같은 색이면 안된다.
첫번째 집과 마지막 집도 같은 색이면 안된다.
N개의 집이 있고, 각 집의 각 색상별 비용이 주어진다.
즉, 첫번째 집과 마지막 집이 같은색이면 안된다는 조건 때문에 기존 RGB 거리 문제보다 살짝 까다롭다.
그래서 사용한 전략은 다음과 같다.
- 첫번째 집의 색상을 R, G, B 하나로 고정하고 시작한다. 즉 3가지 경우로 나눠서 각각 따로 계산한다.
- 그 다음 집부터는 기존 RGB거리처럼 dp[i][j] = i번째 집을 j색으로 칠할 때의 최소 비용을 채워나간다.
- 마지막 집에서는 첫번째 집과 같은 색이 오지 않도록 확인한다.
예를 들어 집디 3개일때, 다음과 같은 입력이 있다.
26 40 83
49 60 57
13 89 99
각 줄은 각각 집을 빨강, 초록, 파랑으로 칠하는 비용이다.
for first_color in range(3): # 0(R), 1(G), 2(B)
첫번째 집의 색상을 하나로 고정해서 세번 반복한다.
예를 들면 첫 집을 R로 고정 → G, B로 고정 → …
dp = [[INF]*3 for _ in range(N)]
dp[0][first_color] = A[0][first_color]
DP테이블을 초기화 한다.
첫번째 집은 first_color로 고정해서 그 비용만 기록하고, 나머지 두 색은 절대 고르지 않게 INF로 설정한다.
for i in range(1, N):
dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + A[i][0]
dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + A[i][1]
dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + A[i][2]
이전 집에서 다른 두 색중 최소 비용을 선택해서, 현재 색을 선택한다.
예를 들어 현재 집을 빨강으로 칠하고 싶으면 이전 집은 초록 / 파랑 중 최소를 택해야 한다.
for last_color in range(3):
if last_color != first_color:
answer = min(answer, dp[N-1][last_color])
마지막 집의 색이 첫 집과 같지 않을 때만 답으로 고려하고, dp[N - 1][last_color]은 N - 1번째 집을 특정 색으로 칠한 최소 비용을 나타낸다.
구분 의미
dp[i][j] | i번째 집을 j색으로 칠했을 때의 최소 비용 |
첫 집 색 | 세 가지 경우로 나눠서 DP 세 번 돌림 |
마지막 집 색 | 첫 집 색과 다를 때만 유효한 정답 후보 |
코드
# 백준 17404 - RGB거리 2
# 분류 : 다이나믹 프로그래밍
import sys
input = sys.stdin.readline
INF = 1e9
N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]
answer = INF
for first in range(3) :
dp = [[INF] * 3 for _ in range(N)]
dp[0][first] = A[0][first]
for i in range(1, N) :
dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + A[i][0]
dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + A[i][1]
dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + A[i][2]
for last in range(3) :
if last != first :
answer = min(answer, dp[N - 1][last])
print(answer)