약간 까다로운 파싱 DP문제이다.
Top-Down 방식으로 해결했다.
예외가 없는 경우 모든 초항에 대해서 1로 설정했다.
$$DP[len-1] = 1 $$
$$ DP[N] = \begin{cases} DP[N+1], & \mbox{if arr[N+1] = 0 or arr[N+2] = 0} \\ subDP[N], & \mbox{if arr[N+1]}\ne\mbox{0 and arr[N+2] }\ne\mbox{0} \end{cases} $$
$$ subDP[N] = \begin{cases} DP[N+1] + DP[N+2], & \mbox{if arr[N] = 1} \\ DP[N+1] + DP[N+2], & \mbox{if arr[N] = 2 and 1} \le\mbox{arr[N+1]}\le\mbox{6} \\ DP[N+1], & \mbox{else} \end{cases} $$
2개 항을 더하는 연산에는 MOD연산을 추가로 해주어야 한다.
또한 \( arr[N+1] = 0 \) \(and\) \( arr[N+2] = 0 \) 의 경우는 암호가 만들어지지 않으므로, 0을 출력하고 종료한다.
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | #include <bits/stdc++.h> using namespace std; #define MOD 1000000 int dp[5011]; int main(void) { ios::sync_with_stdio(0); cin.tie(NULL); string s; cin >> s; int len = s.size(); if (s[0] == '0' || len == 0) { cout << 0 << '\n'; return 0; } dp[len] = 1; dp[len - 1] = 1; bool before_zero = false; bool zero_sum = false; if (s[len - 1] == '0') before_zero = true; for (int i = len - 2; i >= 0; i--) { if (before_zero) { if (s[i] == '1' || s[i] == '2') { dp[i] = dp[i + 1]; before_zero = false; zero_sum = true; } else { cout << 0 << '\n'; return 0; } } else { if (s[i] == '0') { before_zero = true; dp[i] = dp[i + 1]; } else if (s[i] == '1') { if (zero_sum) { dp[i] = dp[i + 1]; zero_sum = false; } else { dp[i] = (dp[i + 1] + dp[i + 2]) % MOD; } } else if (s[i] == '2') { if (!zero_sum && s[i + 1] >= '0' && s[i + 1] <= '6') { dp[i] = (dp[i + 1] + dp[i + 2]) % MOD; } else { dp[i] = dp[i + 1]; zero_sum = false; } } else { dp[i] = dp[i + 1]; zero_sum = false; } } } cout << dp[0]; return 0; } | cs |
'Problem Solving > BOJ' 카테고리의 다른 글
[BOJ] 10822 : 더하기 (0) | 2019.01.03 |
---|---|
[BOJ] 14888 : 연산자 끼워넣기 (0) | 2018.12.30 |
[BOJ] 2225 : 합분해 (0) | 2018.12.30 |
[BOJ] 10171 : 고양이 (0) | 2018.12.30 |
[BOJ] 1759 : 암호 만들기 (0) | 2018.12.30 |