https://www.acmicpc.net/problem/1149
문제
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 복사
3
26 40 83
49 60 57
13 89 99
예제 출력 1 복사
96
예제 입력 2 복사
3
1 100 100
100 1 100
100 100 1
예제 출력 2 복사
3
예제 입력 3 복사
3
1 100 100
100 100 100
1 100 100
예제 출력 3 복사
102
예제 입력 4 복사
6
30 19 5
64 77 64
15 19 97
4 71 57
90 86 84
93 32 91
예제 출력 4 복사
208
예제 입력 5 복사
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 복사
253
해당 문제는 각 집을 칠할 때마다 그 전 집이 어떤 색으로 칠해졌는지에 따라 가능한 선택지가 달라집니다. 예를 들어, 2번 집이 빨강으로 칠해졌다면 1번 집은 초록이나 파랑으로 칠해야 합니다. 이런 식으로 각 집마다 그 전 집의 색깔에 의존하게 됩니다. 그리하여 동적 계획법으로 문제를 풀어야 합니다.
모든 경우의 수를 일일이 다 계산하는 것은 비효율적입니다. 각 집의 색에 대한 비용을 저장해 두고, 이미 계산된 결과를 재사용할 수 있다면 훨씬 빠르게 계산할 수 있습니다. 동적 계획법은 바로 이러한 중복 계산을 피하고 문제를 최적화하는 방법입니다.
- dp[i][0]: i번째 집을 빨강으로 칠할 때의 최소 비용
- dp[i][1]: i번째 집을 초록으로 칠할 때의 최소 비용
- dp[i][2]: i번째 집을 파랑으로 칠할 때의 최소 비용
이전 집의 색깔을 고려하면서 현재 집의 최소 비용을 계산할 수 있습니다.
- i번째 집을 빨강으로 칠할 경우:
- dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + costs[i][0]
- 즉, i-1번째 집이 초록이거나 파랑으로 칠해졌을 때의 최소 비용 중 더 작은 값을 선택하고, 현재 집을 빨강으로 칠하는 비용을 더합니다.
- i번째 집을 초록으로 칠할 경우:
- dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + costs[i][1]
- 즉, i-1번째 집이 빨강이거나 파랑으로 칠해졌을 때의 최소 비용 중 더 작은 값을 선택하고, 현재 집을 초록으로 칠하는 비용을 더합니다.
- i번째 집을 파랑으로 칠할 경우:
- dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + costs[i][2]
- 즉, i-1번째 집이 빨강이거나 초록으로 칠해졌을 때의 최소 비용 중 더 작은 값을 선택하고, 현재 집을 파랑으로 칠하는 비용을 더합니다.
마지막 집의 최소값
마지막 집에서 빨강, 초록, 파랑으로 칠하는 세 가지 경우 중에서 가장 작은 값을 선택하면 됩니다:
- result = min(dp[N-1][0], dp[N-1][1], dp[N-1][2])
초기 상태:
1번 집은 빨강, 초록, 파랑으로 각각 칠하는 비용을 바로 DP 테이블에 넣습니다:
2번 집은 이전 집의 색에 의존하여 최소 비용을 구합니다:
3번 집도 마찬가지로 계산:
결과적으로 마지막 집에서 최소값을 선택:
따라서 정답은 96입니다.
n = int(input())
house = [list(map(int,input().split())) for _ in range(n)]
dp = [[0]*3 for _ in range(n)]
dp[0][0] = house[0][0]
dp[0][1] = house[0][1]
dp[0][2] = house[0][2]
for i in range(1,n):
dp[i][0] = min(dp[i-1][1],dp[i-1][2]) + house[i][0]
dp[i][1] = min(dp[i-1][0],dp[i-1][2]) + house[i][1]
dp[i][2] = min(dp[i-1][0],dp[i-1][1]) + house[i][2]
print(min(dp[n-1][0],dp[n-1][1],dp[n-1][2]))
'코딩테스트' 카테고리의 다른 글
[python 백준] 11660번 : 구간 합 구하기 5 (0) | 2024.10.11 |
---|---|
[python 백준] 15666번 : N과 M (12) (1) | 2024.09.25 |
[python 백준] 1932번 : 정수 삼각형 (0) | 2024.09.24 |
[python 백준] 14500 번 : 테트로미노 (골드 4) (0) | 2024.09.23 |
[python 백준] 9019번 : DSLR (1) | 2024.09.13 |