Problem Solving/Baekjoon

[백준/JAVA] 2579 - 계단 오르기

jihyeon99 2024. 7. 19. 12:35

문제 정보

https://www.acmicpc.net/problem/2579

 

문제 

 

문제 해결 과정

완전 탐색 풀이

매 번 계단을 한 칸(+1칸)  또는 두 칸(+2칸)을 오르는 경우, 가능한 경우의 수는 다음과 같다.

 이동 1(+1칸/+2칸) x 이동 2(+1칸/+2칸) x ... x 이동 k(+1칸/+2칸) = 2^k가지

 

이때 계단의 개수가 최대 300개이므로, 이동은 최소 150번(+2칸으로만) 최대 300번(+1칸으로만) 일어나게 된다.

따라서, 150 ≤ k ≤ 300이므로, 2^150 < 시간복잡도 < 2^300일 것이고 문제 시간 제한인 1초를 초과하게 된다.

 

DP 풀이

계단 4에 도착할 수 있는 경우를 주목해보았을 때, 다음과 같이 나뉘어 질 수 있다.

  • 계단 3에서 + 1칸
  • 계단 2에서 + 2칸

연속하여 세 개의 계단을 밟을 수 없으므로, 불가능한 경우를 삭제(위에서 빨간색 x)해 보았다. 삭제된 것들을 보면, 규칙을 찾을 수 있었다. 

+1칸을 이동하여 현재 계단에 도착한 경우, 이전에도 +1칸해서 이동한 경우는 불가능
(+2 +1 +1도 불가능하고, +1 +1 +1도 불가능하다) 

따라서, +1칸을 이동하여 현재 계단에 도착한 경우는, 이전에 무조건 +2칸해서 이동한 경우만 가능함

 

 

즉, 현재 계단의 번호이전에 +1칸을 연속으로 몇 번 이동했는지가 중요한 요소가 된다. 따라서 dp 배열을 2차원으로 다음과 같이 정의하였다.

dp[i][j] : 현재 i번 계단에 도착한 경우, +1칸을 연속하여 j번 이동했을 때의 총점의 최댓값

+2칸 이동 : dp[i][0] = Max(dp[i-2][0], dp[i-2][1], dp[i-2][2]) + i번 계단의 점수
+1칸 이동 : dp[i][1] = dp[i-1][0] + i번 계단의 점수

 

DP 풀이의 시간복잡도

위의 2차원 배열을 1번 계단부터 N번 계단까지 차례대로 채워나가는 시간이므로, 대략 N(계단수) * 2 = 300 * 2 = 600이므로 제한 시간내에 충분히 풀 수 있다.

 

코드

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]; // dp[i][j] : i번째 계단일 때, +1이 연속하여 j번 나왔을때의 총점 최댓값
		
		dp[1][1] = Integer.parseInt(br.readLine()); // +1칸
		
		if(n >= 2) {
			int n2 = Integer.parseInt(br.readLine());
			dp[2][0] = n2; // +2칸
			dp[2][2] = dp[1][1] + n2; // +1칸 +1칸			
		}
		
		for(int i=3; i<=n; i++) {
			int num = Integer.parseInt(br.readLine()); // 현재 적힌 계단의 수
			
			// +1칸하여 계단 밟은 경우
			dp[i][1] = dp[i-1][0] + num; // 그 이전에 +1칸하여 계단 밟으면 안됨 (+1,+1,+1 or +2,+1,+1 모두 불가)
			
			// +2칸하여 계단 밟은 경우
			dp[i][0] = Math.max(Math.max(dp[i-2][0], dp[i-2][1]), dp[i-2][2]) + num;
		}
		
		System.out.println(Math.max(Math.max(dp[n][0], dp[n][1]), dp[n][2])); // 마지막 계단은 반드시 밟아야 함
	}
}

'Problem Solving > Baekjoon' 카테고리의 다른 글

[백준/JAVA] 14501 - 퇴사  (0) 2024.07.19
[SWEA/JAVA] 8275 - 햄스터  (0) 2024.07.11
[백준/JAVA] 12865 - 평범한 배낭  (0) 2024.06.26