관리 메뉴

Storage Gonie

챕터3-8. DP | 문제 풀이2 - (2) 백준 No.10844 : 쉬운 계단 수 본문

알고리즘/알고리즘 기초(코드플러스)

챕터3-8. DP | 문제 풀이2 - (2) 백준 No.10844 : 쉬운 계단 수

Storage Gonie 2019. 5. 8. 22:26
반응형

쉬운 계단 수 문제

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

문제요약

정수 N이 주어지는데 인접한 자리의 수 차이가 모두 1인 수를 '계단 수' 라고 칭한다. ex) 45656
길이가 N인 계단 수의 개수를 구하고 1000000000로 나눈 나머지를 출력하라.

해결 방법

1. D[N] 에 어떤 값을 저장할 것인지 문장으로 정의해줘야 한다.
- D[N][L] = "L로 끝나는 길이가 N인 '계단 수' 의 개수"

- 이전 문제에서는 0 또는 1만 왔는데, 여기는 한 자리에 0~9가 올 수 있기 때문에 1차원으로 문제를 풀 수 없다.
   따라서 2차원 배열을 활용하게 된다.

2. D[N]의 값을 어떻게하면 찾을 수 있을지 점화식을 생각한다.
- 정수 N이 주어지고, 앞에 어떤 조합이 존재하고 마지막 조합에서 아래와 같은 방법 중 1가지를 선택할 수 있다.

 

case 1) N번째 자리에 L이 올 때 N-1번째 자리에 L-1이 오는 경우

 

case 2) N번째 자리에 L이 올 때 N-1번째 자리에 L+1이 오는 경우

 

따라서, 점화식은 D[N][L] = D[N-1][L-1] + D[N-1][L+1] (1<=L<=8)이고, 

                               L = 0 인 경우, D[N][0] = D[N-1][1] 이고,

                               L = 9 인 경우, D[N][9] = D[N-1][8] 이다.

 

3. 다이나믹 프로그래밍 방법을 적용할 수 있는 문제인지 확인 => 1, 2번을 거쳐야 이게 잘 보임.
- 위와 같이 큰 문제를 작은 문제로 쪼갤 수 있으며, 작은 문제도 큰 문제와 같은 방법으로 풀 수 있고, 작은 문제들이 겹친다.
   (Overlapping SubProblem)
- 문제의 정답을 작은 문제의 정답으로부터 구할 수 있으며, 문제의 크기에 상관없이 어떤 한 문제의 정답은 일정하다.
   (Optimal Substructure)

 

4. 코드구현

- 1000000000으로 나눈 나머지를 구하라는 유형의 문제이기 때문에 d 배열에 나머지를 저장해줘야 한다는 것을 주의하자.
   또한, 마지막 출력할 전 d[n][0] ~ d[n][9] 를 모두 더하는데 이 더한 값 또한 1000000000 으로 나눠줘야 한다는 것을 명심하자.

<Top-down 방식>

2차원 배열을 사용하므로 Bottom-up 방식으로 쉽게 구하자.

<Bottom-up 방식>

(1) 구현
-> 'for문을 이용한 반복문'으로 구현

#include <iostream>

using namespace std;

int d[101][10];

int main()
{
    int n;
    cin >> n;

    // n이 1일 때 결과가 9이므로 해주는 초기화
    for (int i = 1; i <= 9; i++)
        d[1][i] = 1;

    // d 계산하기
    for (int i = 2; i <= n; i++)
    {
        for(int j = 0; j <= 9; j++)
        {
            if (j == 0)
                d[i][j] = d[i-1][j+1];

            else if (j == 9)
                d[i][j] = d[i-1][j-1];

            else
                d[i][j] = d[i-1][j-1] + d[i-1][j+1];

            d[i][j] %= 1000000000;
        }            
    }

    // 구해진 d 합하여 출력하기
    long long sum = 0;

    for(int i = 0; i <= 9; i++)
        sum += d[n][i];
        
    cout << sum % 1000000000 << endl;
}

(2) 시간복잡도
= for 문의 반복 횟수 

= 9 * N = O(N)

반응형
Comments