▽문제 바로가기
https://codeup.kr/problem.php?id=4564
입력
첫째 줄에 계단의 개수가 주어진다.
둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다.
계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10000이하의 자연수이다.
출력
첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최대값을 출력한다.
문제 풀이
규칙
1. 계단은 한 번에 한게단씩 또는 두 계단씩 오를 수 있다.
2. 연속된 세 개의 계단을 모두 밟지 못한다.
3. 마지막 계단은 반드시 밟아야 한다.
계단은 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10000이하의 자연수이다.
규칙을 먼저 찾아봅시다. 계단의 점수를 stairs[i]에 저장했다고 하면
1계단은
1계단
2계단은
1계단-1계단
2계단
3계단은
1계단-1계단-1계단
1계단-2계단
2계단-1계단
연속된 세 개의 계단을 밟을 수 없으므로 두 가지의 경우의 수가 존재합니다.
마지막으로, 하나만 더 해봅시다.
4계단은
1계단-1계단-1계단-1계단
2계단-1계단-1계단
1계단-2계단-1계단
1계단-1계단-2계단
2계단-2계단
마찬가지로 연속된 세 개의 계단을 밟을 수 없으므로 세 가지의 경우의 수가 존재합니다.
이렇게 경우의 수를 구하다 보니 특징 두 가지가 존재합니다.
1. n-1계단을 밟으면 n-2계단은 밟지 못합니다. n-3계단을 밟아야 합니다.
f(n) = f(n-3) + stairs[n-1] + stairs[n]
2. n-1계단을 밟지 않으면 n-2계단을 무조건 밟습니다.
f(n) = f(n-2) + stairs[n]
단, f(n-3)과 f(n-2)는 지금까지 해당 계단을 오르는 경우의 수들의 값 중 가장 큰 값이어야 합니다.
#include <stdio.h>
int memo[301]={0}; //메모
int stairs[301] ={0}; //계단값 저장
int mymax(int a, int b){
return a>b? a:b;
}
int recur(int a){
if(a<0) return 0;
if(a==1) return memo[1] = stairs[1];
if(a==2) return memo[2] = stairs[1] + stairs[2];
if(memo[a]!=0) return memo[a];
else return memo[a] = mymax(recur(a-3)+stairs[a-1], recur(a-2))+stairs[a];
}
int main(){
int a, b;
scanf("%d", &a);
for(int i=1;i<a+1;++i){
scanf("%d", &stairs[i]);
}
printf("%d\n", recur(a));
return 0;
}
'알고리즘' 카테고리의 다른 글
[C/C++] 선택 정렬같은 버블 정렬 구현(선택정렬 + 버블정렬) (0) | 2020.01.08 |
---|---|
[C/C++] 선택 정렬(selection sort) 알고리즘을 활용한 오름차순정렬 (0) | 2020.01.07 |
[C/C++] 코드업(codeup) 3733번 우박수 길이 (3n+1) (large) (0) | 2020.01.05 |
[C/C++] 코드업(codeup) 3704번 계단 오르기 2 (0) | 2020.01.04 |
[C/C++] 코드업(codeup) 3702번 파스칼의 삼각형 2 (0) | 2020.01.01 |