백준 2579: 계단 오르기

📊 결과

💻 내 코드 (Try 1)

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

class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        boolean[] isSeq = new boolean[N+1];
        int[] stairs = new int[N+1];
        int[][] stairsCum = new int[N+1][2];
        // stairsCum[n][0] = 이전 계단 포함
        // stairsCum[n][1] = 이전 계단 스킵

        stairs[0]=0;
        for(int i=1; i<stairs.length; i++){
            stairs[i]=Integer.parseInt(br.readLine());
            stairsCum[i][0]=0;
            stairsCum[i][1]=0;
        }

        stairsCum[1][0] = stairs[1];
        stairsCum[1][1] = stairs[1];
        for(int i=2; i<stairsCum.length; i++){
            stairsCum[i][0] = stairsCum[i-1][1] + stairs[i];
            stairsCum[i][1] += stairsCum[i-2][1]>stairsCum[i-2][0]?stairsCum[i-2][1]:stairsCum[i-2][0];
            stairsCum[i][1] += stairs[i];
        }

        int answer = stairsCum[N][1]>stairsCum[N][0]?stairsCum[N][1]:stairsCum[N][0];
        System.out.println(answer);
    }
}

📝 평가

✔ 잘한 점

  1. DP 상태 정의
    • 2차원 배열로 “이전 계단 포함/스킵” 상태 분리
    • 연속 3칸 제약을 상태로 관리
  2. 점화식 이해
    • 현재 계단 = (이전 계단 밟음) or (이전 계단 안 밟음)
    • 각 경우의 최댓값 추적

✘ 개선점

1. 불필요한 변수

boolean[] isSeq = new boolean[N+1];  // 선언만 하고 미사용

2. 초기화 중복

for(int i=1; i<stairs.length; i++){
    stairs[i]=Integer.parseInt(br.readLine());
    stairsCum[i][0]=0;  // 배열은 기본값이 0
    stairsCum[i][1]=0;  // 불필요한 초기화
}

3. 경계 조건 미처리

N=1일 때 stairsCum[2] 접근하면 IndexOutOfBoundsException 위험


✨ 최적화된 풀이

import java.io.*;

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[] stairs = new int[N+1];
        int[][] dp = new int[N+1][2];
        // dp[i][0] = i번째 계단을 한 칸으로 올라옴 (i-1 밟음)
        // dp[i][1] = i번째 계단을 두 칸으로 올라옴 (i-1 안 밟음)

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

        dp[1][0] = stairs[1];
        dp[1][1] = stairs[1];

        for(int i=2; i<=N; i++){
            // 한 칸 올라옴 = 직전은 반드시 두 칸으로 올라온 경우
            dp[i][0] = dp[i-1][1] + stairs[i];
            
            // 두 칸 올라옴 = i-2의 최댓값
            dp[i][1] = Math.max(dp[i-2][0], dp[i-2][1]) + stairs[i];
        }

        System.out.println(Math.max(dp[N][0], dp[N][1]));
    }
}

변경 사항:


💡 핵심 인사이트

DP 상태 설계

현재 계단에 도착하는 2가지 방법:

  1. 이전 계단(i-1) 밟고 옴 → 1칸 점프
  2. 두 칸 전(i-2)에서 옴 → 2칸 점프

제약 조건 처리:

점화식

dp[i][0] = dp[i-1][1] + stairs[i]  // 1칸 점프
dp[i][1] = max(dp[i-2][0], dp[i-2][1]) + stairs[i]  // 2칸 점프

📚 관련 개념

DP 상태 분리 패턴

비슷한 문제

  1. 백준 1463: 1로 만들기
  2. 백준 1149: RGB거리
  3. 백준 2156: 포도주 시식 (3연속 제약)

🎯 다음 단계

연습 포인트


🏷️ Keywords

#백준 #DP #계단오르기 #동적계획법 #알고리즘 #Java #BOJ2579