Suhwanc

문제 링크 : https://www.acmicpc.net/problem/17404

 

17404번: RGB거리 2

RGB거리에 사는 사람들은 집을 빨강, 초록, 파랑중에 하나로 칠하려고 한다. 또한, 그들은 모든 이웃은 같은 색으로 칠할 수 없다는 규칙도 정했다. 집 i의 이웃은 집 i-1과 집 i+1이고, 첫 집과 마지막 집도 이웃이다. 각 집을 빨강으로 칠할 때 드는 비용, 초록으로 칠할 때 드는 비용, 파랑으로 드는 비용이 주어질 때, 모든 집을 칠하는 비용의 최솟값을 구하는 프로그램을 작성하시오.

www.acmicpc.net

풀이

다이내믹 프로그래밍 문제입니다!

RGB거리에 사는 사람들은 빨강, 초록, 파랑 3가지 색 중 하나로 집을 칠해야하는데, 

인접한 집의 색이 같으면 안된다.

 

따라서 i번째 집의 색은 i-1번째 집의 색에 따라 경우의 수가 나뉘는데,

예를 들어 i-1번째 집이 빨간색이라면, i번째집은 i-1번째 집이 초록, 파랑일 때 1부터 i-1번째 집까지 색칠하는 경우의 수를 모두 더해주면 된다.

 

따라서 dp로 표현하자면 D[i][j] = i번 째 집이 j색일 경우의 비용의 최솟값 이라고 표현 가능하다.

 

단, 이 문제는 첫 집과 마지막 집도 이웃인 원형 마을의 구조를 갖기 때문에

첫 집을 고정 해둔 채 마지막 집의 색을 구해줘야 한다.

 

따라서, d[i][j] 배열을 색깔에 따라 3가지 만들어주고, i가 n번 째 집일 경우 반드시 첫 번째 집의 색과 다른 색으로 칠하는 경우의 수를 구해주면 된다.

 

소스 코드

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <algorithm>
using namespace std;
 
int red[3][1001];
int green[3][1001];
int blue[3][1001];
int r[1001]; int g[1001]; int b[1001];
int main()
{
    int n; scanf("%d"&n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d"&r[i], &g[i], &b[i]);
    }
    // 0: red, 1 : green, 2 : blue
    red[0][1= r[1];
    red[1][2= r[1+ g[2]; red[2][2= r[1+ b[2]; red[0][2= 9999;
    for (int i = 3; i < n; i++) {
        red[0][i] = min(red[1][i - 1], red[2][i - 1]) + r[i];
        red[1][i] = min(red[0][i - 1], red[2][i - 1]) + g[i];
        red[2][i] = min(red[0][i - 1], red[1][i - 1]) + b[i];
    }
    red[1][n] = min(red[0][n - 1], red[2][n - 1]) + g[n];
    red[2][n] = min(red[0][n - 1], red[1][n - 1]) + b[n];
    int min_red = min(red[1][n], red[2][n]);
 
    //green
    green[1][1= g[1];
    green[0][2= g[1+ r[2]; green[2][2= g[1+ b[2]; green[1][2= 9999;
    for (int i = 3; i < n; i++) {
        green[0][i] = min(green[1][i - 1], green[2][i - 1]) + r[i];
        green[1][i] = min(green[0][i - 1], green[2][i - 1]) + g[i];
        green[2][i] = min(green[0][i - 1], green[1][i - 1]) + b[i];
    }
    green[0][n] = min(green[1][n - 1], green[2][n - 1]) + r[n];
    green[2][n] = min(green[0][n - 1], green[1][n - 1]) + b[n];
    int min_green = min(green[0][n], green[2][n]);
 
    //blue
    blue[2][1= b[1];
    blue[0][2= b[1+ r[2]; blue[1][2= b[1+ g[2]; blue[2][2= 9999;
    for (int i = 3; i < n; i++) {
        blue[0][i] = min(blue[1][i - 1], blue[2][i - 1]) + r[i];
        blue[1][i] = min(blue[0][i - 1], blue[2][i - 1]) + g[i];
        blue[2][i] = min(blue[0][i - 1], blue[1][i - 1]) + b[i];
    }
    blue[0][n] = min(blue[1][n - 1], blue[2][n - 1]) + r[n];
    blue[1][n] = min(blue[0][n - 1], blue[2][n - 1]) + g[n];
    int min_blue = min(blue[0][n], blue[1][n]);
    int ans = min(min_red, min(min_green, min_blue));
    printf("%d\n", ans);
 
    return 0;
}
cs

실력이 모자라서 배열도 많고 코드도 길어진거같다 ㅠㅠ

처음 집이 fix가 되기 때문에 각각의 D 배열은 최소 2번째 집까지는 지정을 해주어야

무난하게 점화식으로 풀 수 있었다. (아마 다른 곳에 더 좋은 코드가 있을겁니당 ㅠ)

 

개발환경 : Visual Studio 2019

지적, 조언 언제든지 환영입니다~~

'백준 문제풀이' 카테고리의 다른 글

백준 9019번 DSLR  (0) 2020.01.20
백준 1697번 숨바꼭질  (0) 2020.01.16
백준 1309번 동물원  (0) 2020.01.16
백준 17087 숨바꼭질 6  (0) 2020.01.16
백준 17299번 오등큰수  (0) 2020.01.16