https://www.acmicpc.net/problem/2579
2579번: 계단 오르기
계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림 1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점
www.acmicpc.net
접근법 :
**1) 어떻게 풀 것인가?**
이 문제는 dp개념을 사용하여 풀어야한다.
보통 dp[n]은 n에 오기까지 걸린 최대/최소값 으로 정의한다.
(이 문제는 최댓값을 찾는 문제이므로 dp[n]은 n에 오기까지 최댓값이라 정의)
dp란 주어진 문제를 여러개의 작은 문제로 나누어 해결하고, 기존에 해결된 문제의 해결법을 재활용하는 알고리즘이다.
아래 그림에서 계단은 순서대로 1,2,3....의 index를 가진다고 가정한다.
규칙)
- 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.
- 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.
- 마지막 도착 계단은 반드시 밟아야 한다.
위 그림을 보고 아래와 같은 사항을 이해할 수 있다.
1. 첫번째 계단에 올랐을때 가지는 최댓값은 첫번째 계단을 밟는 방법이다.
2. 두번째 계단을 오르는 방법에는
(1) 처음부터 두번째 계단 밟기
(2) 첫번째계단, 두번째 계단 밟기
두 방법이 있는데 (2)는 항상 (1) 이상으로, 두번째 계단을 오르는 방법은 (2)번이어야한다. (조건에 계단은 자연수라고 써있음)
위 사항을 아래와 같이 식으로 정리 가능하다.
1. dp[1] = stairs[1]
2. dp[2] = stairs[1] + stairs[2]
그리고 계단이 3개 이상일때부터 규칙에 따라 dp적으로 식을 생각할 수 있다.
세번째 계단에 오르는 방법에는
1. 시작지점에서 첫번째 계단을 밟고, 한칸 뛰어 세번째 계단을 밟는 경우
2. 시작지점에서 두번째 계단을 밟고 세번째 계단을 밟는 경우
이고 둘 중 더 큰값이 세번째 계단에 오르는 방법이 되어야한다.
라는 사항은
dp[3]
1. dp[1] + stairs[3]
2. dp[0] + stiars[2] + stairs[3]
으로 정리할 수 있고, 이는 n으로 치환하면
dp[n]
1. dp[n-2] + stairs[n] // 직전 계단에서 점프O
2. dp[n-3] + stairs[n-1] + stairs[n] // 직전 계단에서 점프X
이 된다.
그리고 1,2 중 더 큰 값이 무엇인지 비교하여 dp[n] 에 대입하면 된다.
**2) 시간복잡도**
1초이다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수라는 조건이 있는데
해당 시간복잡도는 O(N)으로 시간은 넉넉하다.
**3) 공간복잡도**
128mb이다.
**4) 풀면서 놓쳤던점**
dp에 대하여 이해 못했을때 풀었던 문제라 책을 보고 도움받아가며 풀었다.
이후 완전히 이해하고 삼성 sds 특강에서 한번 더 문제를 풀게되었는데 전에 공부한덕에 문제를 좀 더 쉽게 풀 수 있었다.
**5) 이 문제를 통해 얻어갈 것**
dp에 대한 이해
문제를 다른 방식으로 생각하기 ( 다양한 관점으로)
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.valueOf(br.readLine());
int[] stairs = new int[n+1];
stairs[0] = 0;
for(int i =1; i<=n; i++){
stairs[i] = Integer.valueOf(br.readLine());
}
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = stairs[1];
if(n >=3){
//바보다........ n=1일때 18번줄이 밖에 있으면 에러남 당연함..
dp[2] = stairs[1] + stairs[2];
for(int i =3; i<=n; i++){
int nojump = stairs[i] + stairs[i-1] + dp[i-3];
int onejump = stairs[i] + dp[i-2];
if(nojump > onejump){
dp[i] = nojump;
}
else{
dp[i] = onejump;
}
}
}
else if(n==2){
//그러므로 n이 2일때 경우를 따로 해야함
dp[n] = stairs[1] + stairs[2];
}
System.out.println(dp[n]);
}
}
'study > 백준' 카테고리의 다른 글
[백준문제풀이] 5557 1학년 java (0) | 2023.11.01 |
---|---|
[백준문제풀이] 2580 스도쿠 java (1) | 2023.10.31 |
[백준문제풀이] 2517 달리기 java (0) | 2023.10.27 |
[백준문제풀이] 1697 숨바꼭질 java (0) | 2023.10.27 |
[백준문제풀이] 1644 소수의연속합 자바풀이 (0) | 2023.10.23 |