알고리즘/백준

[백준/c++] 2579번: 계단 오르기

녕이 2022. 2. 22. 19:36
728x90

 

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

 

2579번: 계단 오르기

계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림 1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점

www.acmicpc.net

 

문제 요약

 

1. 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다.

2. 연속된 세 개의 계단을 모두 밟아서는 안된다.

3. 시작점은 계단에 포함되지 않는다.

4. 마지막 도착 계단은 반드시 밟는다.

 

1번째 밟고 2번째 혹은 3번째 계단 오를 수 있다.

1번째 밟고 4번째 혹은 2-3번째 계단을 연속으로 모두 밟을 수 없다.

이 게임에서 얻을 수 있는 총점수의 최댓값 구하기

 

범위 

 

계단의 개수 N (1 ≤ N ≤ 300)

 

 

 


 

 

 

N번째 계단에 도착해 얻는 최대 점수

→ 각 계단에 도착해서 얻을 수 있는 최대 점수를 구하면서 N번째까지 이동하면 N번째 계단에 도착해서 얻는 최대 점수를 구할 수 있다.

 

 

초기값은 계단 바로 밑부터 시작하므로 0에서 시작한다.

각 i번째 계단의 최대 점수를 담는 dp 이차원 배열을 선언한다.

dp [i][0] = i-2에서 한 칸을 건너뛰어 i로 올라온 경우의 점수

dp [i][1] = i-1에서 i로 올라온 경우의 점수

 

 

이런 문제는 규칙을 찾으면 쉽게 코드를 짤 수 있는데, 우선 규칙을 찾아보자.

i번째 계단에 도착할 수 있는 방법에 대해서 생각을 해보면 규칙이 나타난다.

 

5번 계단에 오른다고 생각해보자.

 - 4번 계단에서 오르는 경우(i-1에서 i로 올라오는 경우의 점수, dp [5][1]):

 

2번에서 4번, 5번으로 올라오는 경우는 가능하지만, 3번-4번-5번은 계단을 연속으로 밟는 경우이므로 무시한다. 2번에서 4번으로 오는 경우의 최대 점수 값은 dp [4][0] 이므로 

dp[5][1] = dp[4][0] + stair[5];

 

 - 3번 계단에서 오르는 경우(i-2에서 i로 올라오는 경우의 점수, dp [5][0]): 

 

이 부분은 2가지 경우가 모두 가능하다. 3번의 최대 점수를 찾아내서 그 값을 더해주면 되는데,

3번으로 오는 경우 두 가지, 2번에서 오는 경우와 1번에서 오는 경우 중 최댓값을 구하고 5번의 점수를 더해주면 된다.

dp[5][0] = stair[5] + max(dp[3][0], dp[3][1]);

 

 

다른 계단에서도 이와 같은 형식으로 진행이 되기 때문에 우리는 규칙을 찾을 수 있다!

dp[i][0] = stair[i] + max(dp[i-2][0], dp[i-2][1]);
dp[i][1] = stair[i] + dp[i-1];

 

초반의 값들은 고정값이 정해져 있다. 

1번 계단은 0보다 작은 값이 없으므로 dp [1][0] = 0, dp [1][1] = stair [1]로 지정해주었다.

또한 2번 계단도 1번에서 오는 경우와 시작점에서 오는 경우가 정해져 있기 때문에 지정해주되, 만약 계단의 개수(n)가 2보다 크거나 같은 경우에만 진행하도록 해주었다.

 

결괏값은 2가지 경우(i-1에서 온 경우, i-2에서 온 경우) 중 최대 점수를 낸 것을 출력해주었다.

 

#include <iostream>
#include <algorithm>
#define num 1002
using namespace std;
int n, stair[num], dp[num][2];

void input(){
    cin >> n;
    stair[0] = 0; //시작점
    for(int i=1; i<=n; i++) cin >> stair[i];
}

void solution(){
    dp[1][0] = 0; dp[1][1] = stair[1];
    if(n>=2){
        dp[2][0] = stair[2];
        dp[2][1] = stair[1] + stair[2];
    }
    
    for(int i=3; i<=n; i++){
        dp[i][0] = stair[i] + max(dp[i-2][0], dp[i-2][1]); //max 값을 넣어야 됨
        dp[i][1] = stair[i] + dp[i-1][0]; //3번 연속으로 오를 수 없기 때문
    }
    cout << max(dp[n][0], dp[n][1]) << '\n';
}

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    input();
    solution();
    return 0;
}

 

 

 

 

 

 

💡공부 및 기록용 블로그이므로 오류가 있을 수 있습니다.💡

만약 문제에 오류나 오타가 있다면 댓글로 알려주세요
언제나 환영합니다. 감사합니다. 화이팅!

 

 

 

 

728x90