Go, Vantage point
가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.
Github | https://github.com/overnew/
Blog | https://everenew.tistory.com/
티스토리 뷰
문제
풀이
다이나믹 프로그래밍 문제이므로 일단 직관적인 top-down 방식으로 풀어보았다.
메모이제이션을 위한 배열 max_stair[300][2] 선언하는데 2차원으로 선언하는 이유는 해당 위치가 직전 계단과 연속되는지를 저장하기 위해서이다.
max_stair[ ][ 0 ] 에는 두 계단을 뛰어 연속되는 계단이 없는 경우를, max_stair[ ][ 1 ] 에는 한 계단만 올라가 이전의 계단과 연속되는 경우를 저장한다.
이후 현재의 계단 위치 stair_idx에서 연속되는 계단 수인 succession가 1인 경우에만 한 계단만 오를 수 있도록 ascendStair(stair_idx+1, succession+1)를 재귀호출을 해준다.
두 계단을 올라가는 경우는 계단의 개수를 초과하지 않는 경우 ascendStair(stair_idx+2, 1)를 재귀 호출해준다.
해당 재귀 호출 값들을 max_stair에 저장하여 다이나믹 프로그래밍을 구현한다.
코드
bottom-up 방식
모든 재귀 호출은 for문으로 구현이 가능하다. 해당 문제를 buttom-up방식으로 구현해보자.
계단은 3칸 이상을 연속으로 오를 수 없기 때문에 N번째 계단으로 오르는 경우는 단 두 가지뿐이다.
첫 번째는 직전의 칸(N-1)에서 한 칸만 올라와 N번째에 도달한 경우이다.
이 경우는 N-1과 N이 연속되었으므로 N-1로 도달할 때는 반드시 두 칸을 올라왔어야 한다. 즉, N-3에서 두 칸을 올라온 경우다. 따라서 N-3의 메모이제이션 저장 값을 사용한다.
두 번째는 두 칸을 올라와 N-2에서 N으로 도달한 경우이다.
이 경우는 N-2의 메모이제이션 저장 값을 사용하면 된다.
이를 점화식으로 나타내면 아래와 같다.
1. dp[N] = stair_scores[N-1] + stair_scores[N]+dp[N-3] ;
2. dp[N] = stair_scores[N] + dp[N-2] ;
이를 stair_num-1 까지 순회하여 dp[stair_num-1]에 저장되어 있는 값이 답이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#include <iostream>
using namespace std;
int stair_num;
int stair_scores[300];
int dp[300];
int main() {
cin>>stair_num;
for(int i=0; i<stair_num ; ++i)
cin>>stair_scores[i];
dp[0] = stair_scores[0];
dp[1] = stair_scores[1]+stair_scores[0];
dp[2] = max(stair_scores[0], stair_scores[1] ) +stair_scores[2];
for(int i=3; i<stair_num ; ++i)
dp[i] = max(stair_scores[i-1]+stair_scores[i] + dp[i-3],stair_scores[i] +dp[i-2]);
cout<<dp[stair_num-1]<<'\n';
return 0;
}
|
cs |
'알고리즘 공부 > 백준' 카테고리의 다른 글
[백준] No.1520 - 내리막 길 (C++) (0) | 2020.11.10 |
---|---|
[백준] No.2294 - 동전 2 (C++, BFS구현) (0) | 2020.11.10 |
[백준] No.1149 - RGB거리 (C++) (0) | 2020.11.08 |
[백준] No.2170 - 선 긋기(C++) (0) | 2020.11.07 |
[백준] No.10830 - 행렬 제곱 (C++) (0) | 2020.11.07 |