Post

[TIL] 막혔던 문제 - 백준 10844번 풀이

[TIL] 막혔던 문제 - 백준 10844번 풀이

1. 막히게 된 문제

날마다 백준 실버 ~ 골드 티어의 문제를 풀던 도중 오늘은 어떻게 풀이해야 할 지 감이 안오는 문제를 발견했습니다


처음에는 첫 자리부터 자릿수를 넘길 때마다 + 또는 -가 되니 9 * 2^(자릿수-1)으로 해야하나 싶었는데
이러면 각 자릿수에서 9를 초과하거나 0보다 낮아지는 경우의 예외를 계산하기가 너무 어렵더라구요

전혀 갈피를 못 잡고 있는 채, 결국 질문 게시판에 있는 다른 사람들의 질문이 담긴 코드를 확인해보았습니다


2. 다른 사람의 풀이를 참고해보면…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Integer[][] dp = new Integer[101][10];  // dp[자릿수][끝나는 수]
dp[1] = new Integer[]{0, 1, 1, 1, 1, 1, 1, 1, 1};

for (int i=2; i<N+1; i++) {
    for (int j=0; j<10; j++) {
        if (j==0)
            dp[i][j] = dp[i-1][1];
        else if (j==9)
            dp[i][j] = dp[i-1][8];
        else
            dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1];
        
        dp[i][j] = dp[i][j] % 1_000_000_000;
    }
}

Integer answer = 0;
for (Integer a : dp[N]) answer += a;

천천히 머릿속으로 시뮬레이션을 돌려본 결과… 의외로 단순하게 생각해서 풀어야 했던 문제였습니다
이전에 반드시 이런 풀이는 공식이 있을 것이라 믿었는데 이중 for문으로 경우의 수를 구해야 됐었네요


3. 문제 풀이

처음 dp[1]에는 각각의 경우의 수가 담긴 배열 {0, 1, 1, 1, 1, 1, 1, 1, 1, 1}가 담깁니다
// 0으로 시작할 수 없으니 제외

그리고 N = 2일 경우, dp[2]에는 이전 배열의 +1과 -1 두 개에 위치한 값의 경우의 수를 더합니다
이때, 숫자가 0이 되는 경우와 9가 되는 경우는 각각 1에서 0으로, 8에서 9로 가는 경우만 있으니 따로 계산해줍니다

마지막 for문으로 마지막에 올 수 있는 각 자릿수의 경우의 수를 더하면서
조건에 따라 값을 1,000,000,000으로 나눠주는 작업을 합니다

이때, answer에 더해지는 각 자릿수의 합에도 1,000,000,000을 나눠주는 작업을 추가해주면 됩니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int N = Integer.parseInt(br.readLine());

        // dp[자릿수][0~9로 끝나는 경우의 수]
        int[][] dp = new int[101][10];
        dp[1] = new int[] {0, 1, 1, 1, 1, 1, 1, 1, 1, 1};

        for (int i = 2; i < N+1; i++) {
            for (int j=0; j<10; j++) {
                if (j == 0)
                    dp[i][j] = dp[i-1][1];
                else if (j == 9)
                    dp[i][j] = dp[i-1][8];
                else
                    dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1];

                dp[i][j] %= 1_000_000_000;
            }
        }

        // (마지막 자릿수의 경우의 수 합계 % 1,000_000,000) 출력
        int answer = 0;
        for (int a : dp[N]) answer = (answer + a) % 1_000_000_000;

        bw.write(answer+"\n");
        bw.flush();

        br.close();
        bw.close();
    }
}


img

This post is licensed under CC BY 4.0 by the author.