[프로그래머스] PS/Java

[lv3] 스티커 모으기(2)

SH3542 2024. 11. 4. 21:31

https://school.programmers.co.kr/learn/courses/30/lessons/12971

 

1. dp 배열의 설정

dp[i][Y] - i번째 스티커를 떼어냈을 때 최댓값

dp[i][N] - i번째 스티커를 떼지 않았 때 최댓값

 

2. 뽑는 경우의 수는 2가지 [o x o], [o x x o]

후자의 경우를 위해, i-2번째 까지 고려

 

 

3. 점화식 세우기

 

3-1. dp[i][Y] = Math.max(dp[i-1][N], dp[i-2][Y]) + sticker[i];


dp[i-1][Y] => 불가능
dp[i-2][N] => 항상 dp[i-2][Y] > dp[i-2][N] 이므로 고려할 필요 X

3-2. dp[i][N] = Math.max(dp[i-1][Y],  dp[i-2][Y]]);


dp[i-2][N] => 항상 dp[i-2][Y] > dp[i-2][N] 이므로 고려할 필요 X
dp[i-1][N] => 항상 dp[i-1][Y] > dp[i-1][N] 이므로 고려할 필요 X

 

4. 원형 dp의 처리 - 시작과 끝은 이어져 있음

 

4-1. dp[0][Y] = sticker[0]; 으로 설정했을 경우

dp[마지막][Y] => 불가능

dp[마지막][N] => 가능

 

4-2. dp[0][Y] = 0; 으로 설정했을 경우

dp[마지막][Y] => 가능

dp[마지막][N] => 가능

 

두 가지 경우에 대해 tryDp()한다.

 

--------------------------------------------------------------------

 

원형 DP를 처리하는 방법에 대해 탐구한 것은 3가지다.

arr = [1,2,3,4,5,6] 이라면,

 

1.초기값 설정(dp[0] = 1) 여부에 따라 끝 값을 별도 처리 한다.

=> 본문에서 사용

 

2. [1,2,3,4,5,6], [6,1,2,3,4,5] 두 가지 경우로 탐색한다.

더보기

import java.util.*;
class Solution {
    
    static int N, Y=1;
    public int solution(int sticker[]) {
        int answer = 0;
        
        int dp[][] = new int[sticker.length][2];
        dp[0][Y] = sticker[0];
        answer = tryDp(sticker, dp);
        
        int dp2[][] = new int[sticker.length][2];
        int[] sticker2 = new int[sticker.length];
        
        for(int i=0; i<sticker2.length-1; i++) {
            sticker2[i+1] = sticker[i];
        }
        sticker2[0] = sticker[sticker.length-1];
        
        dp2[0][Y] = sticker2[0];
        
        answer = Math.max(answer, tryDp(sticker2, dp2));
        
        return answer;
    }
    
    public int tryDp(int sticker[], int dp[][]) {
        int max = 0;
        int s = sticker.length-1;
        for(int i=1; i<=s; i++) {
            
            if(i < 2) {
                dp[i][N] = dp[i-1][Y];
                dp[i][Y] = sticker[i];
            }
            else if(i==s) {
                dp[i][N] = Math.max(dp[i-1][Y], dp[i-2][Y]);
            }
            else {
                dp[i][N] = Math.max(dp[i-1][Y], dp[i-2][Y]);
                dp[i][Y] = Math.max(dp[i-2][Y], dp[i-2][N]) + sticker[i];
            }
        }

        return Math.max(dp[s][N], dp[s][Y]);
    }
}

 

3. [1,2,3,4,5], [2,3,4,5,6] 두 가지 범위로 나누어 대해서만 탐색한다.

=> 이런 방법이 있구나 싶었다.

https://school.programmers.co.kr/questions/77264

 

class Solution {

    static int N, Y=1;
    public int solution(int sticker[]) {
        int answer = 0;

        int dp[][] = new int[sticker.length][2];
        answer = tryDp(sticker, dp, false);

        dp = new int[sticker.length][2];
        dp[0][Y] = sticker[0];
        answer = Math.max(tryDp(sticker, dp, true), answer);

        return answer;
    }

    public int tryDp(int sticker[], int dp[][], boolean dtch) {

        int s = sticker.length-1;
        for(int i=1; i<=s; i++) {

            if(i == 1) {
                dp[i][N] = dp[i-1][Y];
                dp[i][Y] = sticker[i];
            }

            else if(i == s) {
                if(dtch) {
                    dp[i][N] = Math.max(dp[i-1][Y], dp[i-2][Y]);
                }
                else {
                    dp[i][N] = Math.max(dp[i-1][Y], dp[i-2][Y]);
                    dp[i][Y] = Math.max(dp[i-1][N], dp[i-2][Y]) + sticker[i];
                }
            }

            else {
                dp[i][N] = Math.max(dp[i-1][Y], dp[i-2][Y]);
                dp[i][Y] = Math.max(dp[i-1][N], dp[i-2][Y]) + sticker[i];
            }
        }

        return Math.max(dp[s][N], dp[s][Y]);
    }
}

'[프로그래머스] PS > Java' 카테고리의 다른 글

[lv3] 보석 쇼핑  (3) 2024.11.05
[lv3] 불량 사용자  (0) 2024.11.05
[lv3] 기지국 설치  (0) 2024.11.04
[lv3] 숫자 게임  (0) 2024.11.04
[lv3] 최고의 집합  (0) 2024.11.04