임지혁코딩 2024. 10. 10. 18:55

 

일단은, 나는 DFS나 BFS를 먼저 떠올린다.

너무 클 거 같다면 

1. 문제를 막 풀고 그 결론이 DP 

2. 앞에서 부터 DP 

(2번의 경우에는 DP[I] = DP[I-1]+_ORIGINAL[I-2]~~ 식으로 할 때, 어디까지 DP의 영향이 닿고, 어디부터 닿지 않는지를 고려하자)

3. 뒤에서 부터 DP (굉장히 어렵다) 

 

이걸 사실 암기처럼 할게 아니고,

1번의 경우는 수학적인 식이 DP라는 말이고 EX) Y = X+1 , Z = 2Y , Z = 2X+2 이런 느낌

2번의 경우, 3번의 경우는 지금 현재의 값이 어디에서 왔는가. 를 고민하고

어디까지 이전 값이 영향을 끼쳐도 되는가, 어디부터 안되는가 고민하면 된다. 

 

또, 단순한 1차원 행렬이 아닐 수도. 
기본적으로 dp가 2차원 행렬에서 이전 값이 다음 값의 어디에 영향을 주는가. 를 고민하는 것이기 때문에. 

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

// The main method must be in a class named "Main".
class Main {
    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()) ;

        int [] Narr = new int [N+1];

        for (int i = 1 ; i<=N ; i++)
            {
                Narr[i] = Integer.parseInt(br.readLine());
            }

        int [] dp = new int [N+1];

        dp[1] = Narr[1];

        if (N>=2)
        {
            dp[2] = Narr[1]+Narr[2];
        }

        for (int i =3 ; i<=N ;i++)
            {
                dp [i] = Math.max(dp[i-1],Math.max(dp[i-2]+ Narr[i],dp[i-3]+Narr[i-1]+ Narr[i]));
            }

        int answer = 0 ;
        for (int i = 0 ; i<=N ; i++)
            {
                answer = Math.max(answer,dp[i]);
            }

        System.out.print(answer);
    }
}

위가 예시 코드이고 다시, 핵심은. 
1. dp는 이전 값 기억 프로그래밍이다.
2. dp로 구현할 것은 무엇인가 (위 코드에선 n번째 포도주를 만났을 때, 최대 값)
3. DP의 제약은 무엇인가 (위 코드에선 3개 연속먹을 수 없음으로, 2개전 최대값까지 먹고 지금 먹고, 3개전 최대값 까지 먹고, 전꺼 먹고, 지금 꺼 먹고)
4. DP시 주의할 것은, 해당 I를 꼭 선택해야 하는 가, 아닌가.


상태 2개를 유지하려고 한다면? -> 2차원 배열을 활용하자. 
LCS로 문자열 A,B를 구분해야 한다거나 할 때.