백준 1149번 - RGB거리
문제
백준 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
풀이
백트레킹으로 접근하기에는 시간복잡도가 안되기 때문에 DP 문제
- 테이블 정의
- D[i] => i번째 집까지 칠할 때 비용의 최솟값으로 정의할 경우 같은 색이 중복되면 안된다는 조건을 충족하는 점화식을 찾기가 매우 어려워짐
- 그래서 다음과 같이 2차원 배열로 처리
D[i][0] => i번째 집까지 칠할 때 비용의 최솟값, 단 i번째 집은 빨강
D[i][1] => i번째 집까지 칠할 때 비용의 최솟값, 단 i번째 집은 초록
D[i][2] => i번째 집까지 칠할 때 비용의 최솟값, 단 i번째 집은 파랑
- D[i] => i번째 집까지 칠할 때 비용의 최솟값으로 정의할 경우 같은 색이 중복되면 안된다는 조건을 충족하는 점화식을 찾기가 매우 어려워짐
- 점화식 찾기
앞에 같은 색깔이 있으면 칠할 수 없기 때문에 K번째 집을 칠할 때 같은 색을 제외한 다른 색 중 최소비용을 고려해야 함
또한 k번째 집의 최소비용이 R,G,B 중 어떤 것일지 모르기 때문에 3개의 색칠 비용을 다 구해야 됨
D[k][0] = min(D[k-1][1], D[k-1][2] +R[k]
D[k][1] = min(D[k-1][0], D[k-1][2] +G[k]
D[k][2] = min(D[k-1][0], D[k-1][1] +B[k]
- 초기값 채우기
점화식에 k-1까지 밖에 없기 때문에 가장 처음집의 3가지 색깔 비용만 채워주면 됨
D[1][0] = R[1]
D[1][1] = G[1]
D[1][2] = B[1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
int house[1005][3];
int dp[1005][3];
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 3; j++)
cin >> house[i][j];
}
dp[0][0] = house[0][0];
dp[0][1] = house[0][1];
dp[0][2] = house[0][2];
for (int i = 1; i < n; i++)
{
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];
}
cout << min({ dp[n - 1][0], dp[n - 1][1], dp[n - 1][2] });
return 0;
}
비슷한풀이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <bits/stdc++.h>
using namespace std;
int d[1005][3];
int r[1005], g[1005], b[1005]; //색깔배열을 3개로 분리
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> r[i] >> g[i] >> b[i];
d[1][0] = r[1];
d[1][1] = g[1];
d[1][2] = b[1];
for (int i = 2; i <= n; i++)
{
d[i][0] = min(d[i - 1][1], d[i - 1][2]) + r[i];
d[i][1] = min(d[i - 1][0], d[i - 1][2]) + g[i];
d[i][2] = min(d[i - 1][0], d[i - 1][1]) + b[i];
}
cout << *min_element(d[n], d[n] + 3);
}
댓글남기기