문제
N개의 집을 빨강, 초록, 파랑 중 하나로 칠하되, 인접한 집과 다른 색이어야 한다. 추가로 1번 집과 N번 집도 다른 색이어야 한다(원형). 최소 비용을 구하라.
핵심 아이디어
- 원래 RGB거리(BOJ 1149)에서 원형 조건만 추가된 문제다.
- 1번 집의 색을 R/G/B 중 하나로 고정하고, 각 경우에 대해 DP를 수행한다.
- 마지막 집에서 1번 집과 다른 색인 경우만 답 후보로 채택한다.
- 고정하지 않은 색의 1번 집 비용을 INF로 설정하여 선택을 차단한다.
풀이
#include <iostream>
using namespace std;
int town[3][1001];
int dp[3][3][1001];
int main() {
int n, res = 1000 * 1000 + 1;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> town[0][i] >> town[1][i] >> town[2][i];
}
for (int c = 0; c < 3; c++) { // 1번 집의 색 고정
for (int i = 0; i < 3; i++) {
dp[c][i][0] = town[c][0];
}
for (int i = 1; i <= n; i++) {
dp[c][0][i] = town[0][i] + min(dp[c][1][i-1], dp[c][2][i-1]);
dp[c][1][i] = town[1][i] + min(dp[c][0][i-1], dp[c][2][i-1]);
dp[c][2][i] = town[2][i] + min(dp[c][0][i-1], dp[c][1][i-1]);
// 1번 집과 같은 색은 INF로 차단
if (i == 1) dp[c][c][i] = 1000 * 1000 + 1;
}
for (int j = 0; j < 3; j++) {
if (c == j) continue; // 마지막 집이 1번과 같은 색이면 제외
res = min(dp[c][j][n - 1], res);
}
}
cout << res << endl;
return 0;
}
주요 포인트
dp[c][][]의 c는 1번 집에 고정한 색을 의미한다.i == 1일 때 1번 집과 같은 색(c)의 DP값을 INF로 설정하여 2번 집이 1번과 같은 색을 선택하지 못하게 한다.- 최종 답을 구할 때 마지막 집(n-1)의 색이 c와 다른 경우만 후보로 넣는다.
복잡도
- 시간: O(3 × N) = O(N)
- 공간: O(3 × 3 × N) = O(N)
원형 DP의 전형적인 해법, 한 쪽 끝을 고정하고 여러 번 DP를 돌리는 패턴이다.
댓글