[백준 baekjoon] 1149번 RGB거리 (동적 계획법 dp) 자바 Java 풀이

박소은·2024년 6월 17일
0

알고리즘 공부

목록 보기
6/13
post-custom-banner

문제

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. 백트랙킹 + 재귀

import java.io.*;
import java.util.*;

class Main {

    public static long[] dp;

    public static int[][] cost;

    public static int val_tmp = 0;


    public static int val = Integer.MAX_VALUE;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int N = Integer.parseInt(br.readLine());

        cost = new int[N][3];

        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());

            cost[i][0] = Integer.parseInt(st.nextToken());
            cost[i][1] = Integer.parseInt(st.nextToken());
            cost[i][2] = Integer.parseInt(st.nextToken());

        }

        dfs(-1, 0, N);


        bw.write(String.valueOf(val));
        bw.flush();

        bw.close();
    }


    public static void dfs(int prev, int depth, int N) {

        if (depth == N) {
            val = Math.min(val, val_tmp);
            return;
        }


        for (int i = 0; i < 3; i++) {
            if (prev != i) {
                val_tmp += cost[depth][i];
                dfs(i, depth + 1, N);
                val_tmp -= cost[depth][i];
            }
        }


    }


}
  • 시간 초과 발생

2. 동적 계획법

import java.io.*;
import java.util.*;

class Main {

    public static int[][] dp;

    public static int[][] cost;


    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int N = Integer.parseInt(br.readLine());

        cost = new int[N][3];
        dp = new int[N][3];

        for (int i = 0; i < N; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());

            cost[i][0] = Integer.parseInt(st.nextToken());
            cost[i][1] = Integer.parseInt(st.nextToken());
            cost[i][2] = Integer.parseInt(st.nextToken());

        }


        bw.write(String.valueOf(dfs(N)));
        bw.flush();

        bw.close();
    }


    public static int dfs(int N) {

        dp[0][0] = cost[0][0];
        dp[0][1] = cost[0][1];
        dp[0][2] = cost[0][2];

        for (int i = 1; i < N; i++) {
            dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + cost[i][0];
            dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + cost[i][1];
            dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + cost[i][2];
        }

        return Math.min(Math.min(dp[N - 1][0], dp[N - 1][1]), dp[N - 1][2]);
    }


}
  • 동적 계획법을 사용할 때는 문제를 sub problem으로 나눌 수 있는지를 먼저 고민해야 한다. N개의 집이 있을 때 각 집까지의 최소 비용을 구해보자. 첫 번째 집의 최소 비용은 주어진 cost 배열의 RGB 비용과 동일하다. 두 번째 집의 최소 비용은 첫 번째 집까지의 최소 비용 + 지금 집의 비용이다. 이를 마지막까지 반복하여 세 가지의 최소 경로 중 최솟값을 구하면 정답이 된다.

  • Red일 경우
    Cost[N][0] = min( Cost[N-1][1], Cost[N-1][2] ) + Cost[N][0]
  • Green일 경우
    Cost[N][1] = min( Cost[N-1][0], Cost[N-1][2] ) + Cost[N][1]
  • Blue일 경우
    Cost[N][2] = min( Cost[N-1][0], Cost[N-1][1] ) + Cost[N][2]
profile
Backend Developer
post-custom-banner

0개의 댓글