1. 문제 설명
(1) 1~N번까지의 집이 있음. 이 집들을 빨강, 초록, 파랑으로 색칠하려고 함.
(2) 집은 인접한 번호와 색깔이 달라야 함.
예를 들어 1번 집은 2번집과 색깔이 달라야 함. i번 집은 i-1번 집과 i+1번 집과 색깔이 달라야 함.
(3) 각 집을 빨강, 초록,파랑으로 칠했을 때의 비용이 주어질 때, 조건에 맞도록 칠한 최소 비용을 구하라.
2. 접근 방식
KEY WORD
: DP
해당 문제는 생각할 것이 많이 없는 DP 문제이다.
N행 3열의 DP 배열을 만든다. 0행은 빨강, 1행은 초록, 3행은 파랑에 해당하는 행이다. 그렇다면 각 배열의 원소는 무엇을 뜻할까?
만약 dp[i] [2] 라면 i번째 집을 초록으로 칠했을 때의 최소 비용
이다.
dp[3] [0] 은 3번째 집을 빨강으로 칠했을 때의 최소 비용
이다.
이를 어떻게 구할까?
dp의 메모이제이션
을 사용하면 된다. 메모이제이션이란, 이전 정보를 저장해서, 불필요한 중복 계산을 제거하는 방법이다. 여기서는 i번째 집을 빨강, 초록, 파랑 으로 칠했을 때의 최소 비용 정보를 저장해둬서, 다음 i+1번째 집을 칠할 때 최소 비용은 이전 집을 모두 돌아볼 필요 없이, i번째 집을 칠할 때의 최소비용만을 이용해서 구할 수 있게 하는 것이다. 우리는 이를 통해, loop문 한 번만으로 문제의 답을 구할 수 있다. 다음 예시를 보자.
메모이제이션을 이용해 이전 정보를 계속 활용하기 위해선 이전 정보와 현재 정보간의 공식이 필요하다. 이것을 점화식
이라고 한다. 위의 사진은 1번 집을 각 색깔로 칠했을 때의 최소비용이다. 그러면 2번째 집을 각 색깔로 칠했을 때의 최소비용은 어떻게 되는가?
빨강 집 = 2번째 집을 빨강색으로 칠한 비용 + 1번 집을 초록색으로 칠했을 때랑, 파랑색으로 칠했을 때의 최소값
초록 집 = 2번째 집을 초록색으로 칠한 비용 + 1번 집을 빨강색으로 칠했을 때랑, 파랑색으로 칠했을 때의 최소값
파랑 집 = 2번째 집을 파랑색으로 칠한 비용 + 1번 집을 빨강색으로 칠했을 때랑, 초록색으로 칠했을 때의 최소값
이다. 그림으로 표현하면 다음과 같다.
그럼 3번째 집은 어떤가?
3번째 집 또한 3번째 집을 특정 색깔로 칠했을 때의 비용
+ 이전 집을 다른 색깔로 칠한 경우 중 최소 비용
이다.
3번째 집에서의 최소 비용을 구할 때, 1 번째 집까지 조회할 필요가 없는 것이, 이미 2번째 집에서 1~2번까지 다 고려한 최소 비용으로 값을 구해놓았기 때문이다. 따라서 dp 배열의 2번째 집 계산 값들만 보면 된다. 또 구해보면 이렇게 된다.
이제 점화식을 구해보자. 점화식은
dp[i][0] = i번째 집을 0번 색깔로 칠했을 때의 비용 + Math.min(dp[i-1][1], dp[i-1][2]);
이다. 물론 위의 식은 초록색으로 칠했을 때의 dp이고, 빨강색으로 칠할 때와 파랑색으로 칠할 때는 이전의 집과 색깔이 안 겹치도록 번호를 바꿔가며 점화식을 만들어주면 된다.
3. 코드 풀이
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int [][] dp = new int [N+1][3];
for (int i = 1; i <= N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int red = Integer.parseInt(st.nextToken());
int green = Integer.parseInt(st.nextToken());
int blue = Integer.parseInt(st.nextToken());
dp[i][0] = red + Math.min(dp[i-1][1], dp[i-1][2]);
dp[i][1] = green + Math.min(dp[i-1][0], dp[i-1][2]);
dp[i][2] = blue + Math.min(dp[i-1][0],dp[i-1][1]);
}
Arrays.sort(dp[N]);
System.out.println(dp[N][0]);
}
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
[백준] 2302 극장 좌석 java (0) | 2024.09.24 |
---|---|
[백준] 11057 오르막수 java 문제 풀이 (0) | 2024.09.21 |
[프로그래머스] n*2 배열 자르기 문제 풀이 java (0) | 2024.09.05 |
[프로그래머스] 행렬 테두리 회전하기 문제 풀이 java (0) | 2024.09.05 |
99클럽 코테스터디 31일차 TIL + [프로그래머스] 네크워크 java 풀이 (0) | 2024.08.21 |