Processing math: 100%
본문으로 바로가기

[BOJ 2579] (DP)계단 오르기(C++)

category AlgorithmsDP 4년 전

계단 오르기 (Silver 3)

문제

전체 문제 보기

 

2579번: 계단 오르기

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

www.acmicpc.net

접근법

이 문제는 예전에 풀었던 BOJ 2156 포도주 시식 문제와 상당히 비슷하다.(포도주 시식 풀이) 포도주 시식 문제와의 차이점은 이 문제에서는 반드시 마지막 계단을 포함해야 한다는 점이다. 이번 문제에서도 3개의 계단을 연속으로 밟을 수 없다. 그래서 임의의 위치 n에서 점수의 최댓값을 f(n), n의 점수를 a(n)이라고 했을 때 f(n)은 아래의 두 가지 경우 중 큰 값이 이다.

  • 1 부터 n3 까지의 최댓값인 f(n3)a(n2)를 포기하고 a(n1)a(n)을 취하는 경우
  • 1 부터 n2 까지의 최댓값인 f(n2)a(n1)를 포기하고 a(n)을 취하는 경우

이를 점화식으로 정리하면 다음과 같다.

f(n)=max(f(n3)+a(n1)+a(n),f(n2)+a(n1))

구현

중복된 계산을 줄이기 위해서 한번 계산한 값은 cache 배열에 저장한다. 그리고 바텀업 방식으로 구현하였다.

#include <iostream>
#include <algorithm>
#include <array>
#define endl '\n'

using namespace std;
int main()
{
    //입출력 성능향상을 위한 설정
    ios_base::sync_with_stdio(false);
    cout.tie(NULL);
    cin.tie(NULL);
    const int MAX = 301;

    array<int, MAX> cache{};
    array<int, MAX> num{};
    int N; //N은 300이하의 자연수
    cin >> N;

    for (int i = 1; i <= N; ++i)
    {
        cin >> num[i];
    }

    cache[1] = num[1];
    cache[2] = num[1] + num[2];

    for (int i = 3; i <= N; ++i)
    {
        cache[i] = max( cache[i - 3] + num[i - 1] + num[i], cache[i - 2] + num[i]);
    }

    cout << cache[N];
    return 0;
}

성능 평가

1부터 N까지의 최댓값을 하나씩 계산하기 때문에 시간 복잡도는 O(n)이다. 그리고 중복된 계산을 피하기 위해 모든 계산 결과를 cache 배열에 저장하고 N개 계단의 점수도 모두 저장하기 때문에 공간 복잡도 또한 O(n)이다.