백준 17404 RGB거리 2
RGB거리 2
이전에 봤던 문제 RGB거리와 거의 유사한 문제다. 조건 첫집과 마지막 집도 이웃이다만 추가되었다.
하지만 말이 이전에 봤던 문제지 거의 1년 전에 봤던 문제고, dp도 오랜만에 봐서 새로운 문제 느낌이었다.
문제분석
- i는 i+1, i-1과 이웃이다.
n번째 집을 기준으로 생각하기 때문에 i+1은 굳이 생각하지 않아도 된다.
- 이웃은 같은 색을 칠할 수 없다.
이번 집이 빨간색으로 칠하려면 이전 집이 초록이나 파랑을 칠해야 한다.
여기서 점화식을 생각해볼 수 있다. d[n][2] = min(solve(n - 1, 0, first), solve(n - 1, 1, first)) + h[n][color]; - 처음 집과 마지막 집은 이웃이다.
조건이 까다롭다고는 하는데 나는 그런 생각은 못했다.
그냥 재귀함수에 마지막 집의 색을 줘서 처음 집의 색이 같으면 큰 수를 줘버렸다.
문제풀이 소감
두번 틀렸는데 그 이유는 세번 반복할때 초기화를 안해줬다.
마지막 집의 색이 무엇이냐에 따라 값이 바뀐다는 사실을 인지하지 못했었다.
다행히 반례를 금방 찾아서 해결했지만 자꾸 사소한 부분에서 실수한다.
연습량이 부족해서 그런 실수들을 하는 것 같다.
그래도 알고리즘 실력이 많이 늘은게 느껴진다. 다만 연습량을 채우기 위해 dp문제를 많이 풀어볼 예정이다.
소스
#include <iostream>
#include<algorithm>
using namespace std;
int n;
int h[1001][3] = { 0 };
int d[1001][3] = { 0 };
bool visited[1001][3] = { 0 };
int solve(int n, int color, int first) {
if (n == 1)
{
if (color == first) {
return 20000000;
}
else
return h[n][color];
}
if (visited[n][color])
return d[n][color];
visited[n][color] = true;
if (color == 0) {
d[n][0] = min(solve(n - 1, 1, first), solve(n - 1, 2, first)) + h[n][color];
}
if (color == 1)
{
d[n][1] = min(solve(n - 1, 0, first), solve(n - 1, 2, first)) + h[n][color];
}
if (color == 2)
{
d[n][2] = min(solve(n - 1, 0, first), solve(n - 1, 1, first)) + h[n][color];
}
return d[n][color];
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 0; j < 3; j++)
cin >> h[i][j];
int ans = 2000000;
if (n == 1)
{
ans = min(min(h[1][0], h[1][1]), h[1][2]);
}
else {
for (int k = 0; k < 3; k++)
{
for (int i = 0; i <= n; i++)
for (int j = 0; j < 3; j++)
visited[i][j]=0;
ans = min(ans, solve(n, k, k));
}
}
cout << ans;
}
댓글남기기