안녕하세요. 회사와 함께 성장하고 싶은 KOSE입니다.

 

이번 포스팅은 백준 10844번의 계단 오르기 문제를 해결한 과정을 정리하고자 합니다.

 

해당 문제는 N자리 숫자의 계단 수를 구하는 문제입니다.

 

1. 문제 해결 과정

1) n == 1일 때,

- 한자리 숫자의 경우 1 ~ 9까지 총 9개가 계단수입니다.

 

2) n == 2 일 때,

- 두 자리 숫자의 경우,  총 17개입니다.

12, 23, 34, 45, 56, 67, 78, 89 (8개)

10, 21, 32, 43, 54, 65, 76, 87, 98 (9개)

 

3) n == 3일 때,

- 세 자리 숫자의 경우, 총 32개입니다.

123, 234, 345, 456, 567, 678, 789 (7개)

987, 876, 765, 654, 543, 432, 321, 210 (8개)

101, 212, 323, 434, 545, 656. 767, 878, 989 (9개)

121, 232, 343, 454, 565, 676, 787, 898 (8개)

 

이 문제에서는 n번째 자리에 위치한 숫자는

(n - 1) 번째 자리 숫자보다 1 작은 수가 나올 수 있는 경우의 수  + (n -1) 번째 자리 숫자보다 1 큰 수가 나올 수 있는 경우의 수로

DP를 구현할 수 있습니다.

이를 그림으로 확인하면 다음과 같습니다.

따라서, 이를 알고리즘화 하면 아래의 코드로 구현할 수 있습니다. 

stair[i][j] = stair[i - 1][j - 1] + stair[i - 1][j + 1]

 

2. 주의할 점 

하지만, 주의할 점은 0보다 작은 자연수는 없으므로 자리 숫자에 0이 있으면 경우의 수는 (위치한 자릿수 - 1)의 1 큰 수의 경우만 고려해야 합니다.

stair[i][0] = stair[i - 1][1]

또한, 9는 9보다 1이 큰 한자리 숫자는 없으므로, (위치한 자리수 - 1)의 1 작은 수의 경우만 고려해야 합니다.

stair[i][9] = stair[i - 1][8]

 

마지막으로, 해당 알고리즘 결과를 제출하는데 여러 번 오답이 발생했습니다.

그 이유는, 최종 결과를 도출하는 과정에서 중간에 이미 long의 범위를 벗어나서 올바른 값을 도출하지 못했기 때문입니다.

(자바 long의 범위는 -2^63 ~ 2^63 -1)입니다.

 

해결책은 모듈러 연산을 적용하는 것입니다.

 

모든 경우의 수는 마지막 자릿수의 1부터 ~ 9까지의 경우를 더하면 완성이 됩니다. 이후, 10억으로 나눠도 되지만,

연산 가능 범위를 벗어날 수 있으므로, 모듈러 연산을 적용하여 각 배열에 저장할 때마다 MOD로 나머지 연산을 해주고 

최종적으로 마지막 숫자들을 더한 후, 다시 MOD로 나머지 연산을 해주면 동일한 결과를 얻을 수 있습니다.

        long result = 0L;
        for (int i = 0; i < 10; i++) {
            result += stair[N][i];
        }
(A + B) % p = ((A % p) + (B % p)) % p

 

3. 최종 소스 코드

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main10844 {

    static final long MOD = 1000000000;
    static int N;
    static long[][] stair;

    public static void main(String[] args) throws IOException {

        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        N = Integer.parseInt(bf.readLine());
        stair = new long[N + 1][10]; // (n 자리수), (0 ~ 9)

        long result = doStairDp();
        System.out.print(result % MOD);
    }

    static long doStairDp() {

        for (int i = 1; i<10; i++) {
            stair[1][i] = 1; // 첫번째 자리수가 i 일때는 모두 1
        }

        for (int i = 2; i <= N; i++) {

            for (int j = 0; j < 10; j++) {

                if (j == 0) {
                    stair[i][0] = stair[i - 1][1] % MOD;
                }

                else if (j == 9) {
                    stair[i][9] = stair[i - 1][8] % MOD;
                }

                else {
                    stair[i][j] = stair[i - 1][j - 1] + stair[i - 1][j + 1] % MOD;
                }
            }
        }

        long result = 0L;
        for (int i = 0; i < 10; i++) {
            result += stair[N][i];
        }

        return result;
    }
}

이상으로, 백준 10844 계단 오르기 문제 해결 과정 정리를 마치겠습니다.

감사합니다.!

 

문제 출처:

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

+ Recent posts