DP

[백준] 1149. RGB거리

hch06 2025. 5. 19. 11:43

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

 

인접한 집의 색이 같으면 안된다는 규칙을 전제로 모든 집을 Red, Green, Blue 중 하나씩으로 칠할 때 모든 집을 칠하는 비용의 최솟값을 구하는 문제이다.

 

처음에 칠할 수 있는 경우의 수가 3가지이고, 무엇으로 칠하냐에 따라 다음 집을 칠할 수 있는 경우의 수도 달라지기 때문에 DP를 이용하여 풀 수 있다.

 

점화식은 다음과 같다.

d[i] = i-1번째 집까지의 최소비용 + i번째 집을 칠할 수 있는 색상 중 최소비용

top-down 형식으로 재귀함수를 이용하여 해결하였는데, 재귀함수 내부 내용은 다음과 같다.

이전 집이 R이면
res = (다음 집이 G일때와 다음 집이 B일때 중 비용이 더 적은 경우가 나오는 것으로 선택)

이전 집이 G이면
res = (다음 집이 R일때와 다음 집이 B일때 중 비용이 더 적은 경우가 나오는 것으로 선택)

이전 집이 B이면
res = (다음 집이 R일때와 다음 집이 G일때 중 비용이 더 적은 경우가 나오는 것으로 선택)

 

중간에 d[depth][rgb중 하나]를 저장하여 이미 확인한 경우의 수는 다시 탐색할 필요 없도록 하여 시간을 절약했다.

 


C

더보기
#include <stdio.h>
#include <string.h>

int d[1000][3];
int cost[1000][3];
int n;

int dp(int depth, int rgb_v){
    if(depth == n-1) return cost[depth][rgb_v];

    if(d[depth][rgb_v] != 0) return d[depth][rgb_v] + cost[depth][rgb_v];

    int a, b;
    if(rgb_v == 0){
        a = dp(depth+1, 1);
        b = dp(depth+1, 2);
        d[depth][rgb_v] = (a < b) ? a : b;
        return d[depth][rgb_v] + cost[depth][rgb_v];
    }
    else if(rgb_v == 1){
        a = dp(depth+1, 0);
        b = dp(depth+1, 2);
        d[depth][rgb_v] = (a < b) ? a : b;
        return d[depth][rgb_v] + cost[depth][rgb_v];
    }
    else{
        a = dp(depth+1, 0);
        b = dp(depth+1, 1);
        d[depth][rgb_v] = (a < b) ? a : b;
        return d[depth][rgb_v] + cost[depth][rgb_v];
    }

}

int main() {
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < 3; j++) scanf("%d", &cost[i][j]);

    int start_r = dp(0, 0);
    int start_g = dp(0, 1);
    int start_b = dp(0, 2);

    if(start_r < start_b)
        printf("%d", (start_r < start_g) ? start_r : start_g);
    else
        printf("%d", (start_b < start_g) ? start_b : start_g);
}

Python

더보기
import sys
sys.setrecursionlimit(10**6)

def dp(depth, rgb_v): # rgb_v: 0->R, 1->G, 2->B
    global cost; global d

    if depth == n-1: return cost[depth][rgb_v] # base check

    if d[depth][rgb_v] != -1: return d[depth][rgb_v] + cost[depth][rgb_v] # 저장된 값 활용

    if rgb_v == 0:
        t = [dp(depth+1, 1), dp(depth+1, 2)]
        d[depth][rgb_v] = min(t)
        
        return d[depth][rgb_v] + cost[depth][rgb_v]
    elif rgb_v == 1:
        t = [dp(depth+1, 0), dp(depth+1, 2)]
        d[depth][rgb_v] = min(t)
        return d[depth][rgb_v] + cost[depth][rgb_v]
    else:
        t = [dp(depth+1, 0), dp(depth+1, 1)]
        d[depth][rgb_v] = min(t)
        return d[depth][rgb_v] + cost[depth][rgb_v]

n = int(input())
cost = []
d = [[-1 for _ in range(3)] for _ in range(n)]
for i in range(n):
    cost.append(list(map(int, input().split())))

start_r = dp(0, 0)
start_g = dp(0, 1)
start_b = dp(0, 2)
res = [start_r, start_g, start_b]

print(min(res))