λ°±μ€€/Gold

[BOJ] 2011 : μ•”ν˜Έμ½”λ“œ

Jaeguk 2022. 3. 3. 13:24
문제 링크

2011번: μ•”ν˜Έμ½”λ“œ (acmicpc.net)

 

2011번: μ•”ν˜Έμ½”λ“œ

λ‚˜μ˜¬ 수 μžˆλŠ” ν•΄μ„μ˜ κ°€μ§“μˆ˜λ₯Ό κ΅¬ν•˜μ‹œμ˜€. 정닡이 맀우 클 수 μžˆμœΌλ―€λ‘œ, 1000000으둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€λ₯Ό 좜λ ₯ν•œλ‹€. μ•”ν˜Έκ°€ 잘λͺ»λ˜μ–΄ μ•”ν˜Έλ₯Ό 해석할 수 μ—†λŠ” κ²½μš°μ—λŠ” 0을 좜λ ₯ν•œλ‹€.

www.acmicpc.net

μ•”ν˜Έκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ κ°€λŠ₯ν•œ ν•΄μ„μ˜ 수λ₯Ό κ΅¬ν•˜λŠ” 문제.

 

풀이

μ•ŒνŒŒλ²³ A~Zλ₯Ό 1~26으둜 μ•”ν˜Έν™” ν•˜κΈ°λ‘œ ν–ˆλ‹€. 띄어쓰기가 μžˆλ‹€λ©΄ 1 1 κ³Ό 11을 ꡬ뢄할 수 μžˆκ² μ§€λ§Œ μ•”ν˜Έμ— 띄어쓰기가 μ—†κΈ° λ•Œλ¬Έμ— μ•”ν˜Έκ°€ 11이라고 ν•˜λ©΄ "AA"와 "K"둜 2κ°€μ§€λ‘œ 해석 κ°€λŠ₯ν•˜λ‹€.

μ—¬κΈ°μ„œ μ£Όμ˜ν•΄μ•Ό ν•  점은 0은 μ•„λ¬΄λŸ° μ•”ν˜Έλ„ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— 해석이 λΆˆκ°€λŠ₯ν•˜λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 10이 λ“€μ–΄μ˜€λ©΄ 1 0 으둜 κ΅¬λΆ„ν•΄μ„œλŠ” 해석할 수 μ—†κ³  10으둜 ν•΄μ„ν•΄μ•Όν•œλ‹€.

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μž…λ ₯으둜 0 ν•˜λ‚˜λ§Œ μ£Όμ–΄μ§„λ‹€λ©΄ 해석이 λΆˆκ°€λŠ₯ν•œ μ½”λ“œμ΄λ―€λ‘œ 0 을 좜λ ₯ν•˜κ³  μ’…λ£Œν•˜λ©΄ λœλ‹€.

μ•„λ¬΄λž˜λ„ 각 자리의 숫자λ₯Ό ν•˜λ‚˜ν•˜λ‚˜ λ΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— int ν˜•λ³΄λ‹€λŠ” string ν˜•μœΌλ‘œ μž…λ ₯λ°›λŠ” 것이 νŽΈν•˜λ‹€.

λ‚˜λŠ” DP배열을 DP[μ‹œμž‘μ ][끝점] 으둜 μ„€μ •ν•΄μ„œ μ‹œμž‘μ λΆ€ν„° 끝점 μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μ•”ν˜Έκ°€ 해석될 수 μžˆλŠ” 경우의 수λ₯Όμ €μž₯ν•΄ λ‘μ—ˆλ‹€.

25114

예제1을 μ˜ˆμ‹œλ‘œ λ“€μžλ©΄ 0~1 인덱슀λ₯Ό 보면 "25"이닀 μ΄λŠ” 2, 5λ‘œλ„ 해석될 수 있고 25λ‘œλ„ 해석될 수 있기 λ•Œλ¬Έμ—

DP[0][1]μ—λŠ” 2의 값을 μ €μž₯ν•΄ λ‘μ—ˆλ‹€. 사싀 μΆœλ°œμ μ€ 항상 0이기 λ•Œλ¬Έμ— DPλ₯Ό ꡳ이 2차원 λ°°μ—΄λ‘œ λ§Œλ“€μ§€ μ•Šμ•„λ„ λμ§€λ§Œ 쀑간에 아이디어λ₯Ό λ°”κΎΈκ²Œ λΌμ„œ μ½”λ“œλ₯Ό 많이 κ³ μΉ˜μ§€ μ•ŠμœΌλ € ν•˜λ‹€λ³΄λ‹ˆκΉŒ μ΄λ ‡κ²Œ 됐닀.

DP[λ¬Έμžμ—΄μ˜ 길이] 둜 1차원 λ°°μ—΄λ‘œ λ§Œλ“œλŠ”κ²Œ λ©”λͺ¨λ¦¬ λ©΄μ—μ„œλŠ” 더 효율적이기 λ•Œλ¬Έμ— 쒋은 μ½”λ“œμ΄λ‹€.

0~2번 μΈλ±μŠ€κΉŒμ§€ 즉 "251"을 λͺ¨λ“  경우의 수둜 λ‚˜λˆ„μ–΄ 보자.

2 5 1, 25 1, 2 51 μ΄λ ‡κ²Œ 3κ°€μ§€κ°€ μžˆλ‹€.

λΉ¨κ°„μƒ‰μœΌλ‘œ μΉ ν•œ 2 5와 25λŠ” 0~1κΉŒμ§€ 봀을 λ•Œ λ‚˜μ˜¬ 수 μžˆλŠ” κ²½μš°μ΄λ‹€.

μ΄ˆλ‘μƒ‰μœΌλ‘œ μΉ ν•œ 2λŠ” 0~0 κΉŒμ§€ 봀을 λ•Œ λ‚˜μ˜¬ 수 μžˆλŠ” κ²½μš°μ΄λ‹€.

DP[0][2] λŠ” DP[0][1] * DP[2][2] + DP[0][0] * DP[1][2] 둜 λ³Ό 수 μžˆλŠ”λ° DP[1][2] λŠ” DP[1][2] 의 값을 κ·ΈλŒ€λ‘œ κ°–κ³ μ˜€λ©΄ μ•ˆλœλ‹€. κ·Έλ ‡λ‹€λ©΄?

μž„μ˜μ˜ μ’Œν‘œ i 에 λŒ€ν•΄ DP[0][i] = DP[0][i-1] * DP[i][i] + DP[0][i-2] * (i-1 ~ i 두 μžλ¦¬κ°€ 자체만으둜 μ•”ν˜Έκ°€ 될 수 μžˆλŠ”μ§€?) 둜 λ³Ό 수 μžˆλ‹€.

μ—¬κΈ°μ„œ 봐야할 점은 λ’€μ˜ 식인 DP[0][i-2] * (i-1 ~ i 두 μžλ¦¬κ°€ 자체만으둜 μ•”ν˜Έκ°€ 될 수 μžˆλŠ”μ§€?) 이 뢀뢄이닀.

2 51 μ΄λ ‡κ²Œ λΆ„λ¦¬ν•΄μ„œ λ³΄λŠ” κ²½μš°μ—λŠ” 뒀에 51을 5 1둜 λ‚˜λˆ„μ§€ μ•Šκ³  51 κ·Έ 자체둜 μ•”ν˜Έλ‘œ 해석될 수 μžˆλŠ”μ§€λ§Œ κ³ λ €ν•˜λ©΄ λœλ‹€. 무슨 말이냐 ν•˜λ©΄ 2 51 μ—μ„œλŠ” 2 5 1 둜 λ‚˜λ‰˜λŠ” κ²½μš°λŠ” 2 5 1 μ—μ„œ 이미 고렀됐기 λ•Œλ¬Έμ— μƒκ°ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

κ·Έλ ‡λ‹€λ©΄ 51은 51 > 26 이기 λ•Œλ¬Έμ— 51 μžμ²΄λ§ŒμœΌλ‘œλŠ” μ•”ν˜Έκ°€ 될 수 μ—†λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— λ’€μ˜ 식은 0이 λœλ‹€.

λ”°λΌμ„œ DP[0][2] = DP[0][1] * DP[2][2] = 2 * 1 = 2

DP[0][3]("2511") = DP[0][2] * DP[3][3] + DP[0][1] * (2 ~ 3 κΉŒμ§€κ°€ 자체만으둜 μ•”ν˜Έκ°€ 될 수 μžˆλŠ”μ§€?)인데

DP[0][2] = μ•žμ—μ„œ κ΅¬ν•œλŒ€λ‘œ  2이고 DP[3][3] = 1이닀.

DP[0][1] = 2 이고 λ’€μ˜ λ‘μžλ¦¬μΈ "11" 은 <= 26 μ΄κΈ°λ•Œλ¬Έμ— 자체만으둜 μ•”ν˜Έκ°€ 될 수 μžˆλ‹€.

λ”°λΌμ„œ DP[0][3] = 2 * 1 + 2  = 4 이닀.

그런데 DP[i][i] 라고 ν•΄μ„œ λ‹€ 값이 1인 것은 μ•„λ‹ˆλ‹€. i 번째 인덱슀 값이 '0' 이라면 DP[i][i] = 0 μ΄λœλ‹€.

μ΄λ ‡κ²Œ ν•΄μ„œ DP[0][N-1] 의 값을 좜λ ₯ν•΄μ£Όλ©΄ μ •λ‹΅.

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
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <stack>
#include <vector>
#include <math.h>
#include <queue>
#include <climits>
#include <algorithm>
#include <iomanip>
#include <map>
#define mod 1000000007
using namespace std;
typedef long long ll;
typedef priority_queue<pair<pair<intint>int>vector<pair<pair<intint>int>>, greater<pair<pair<intint>int>>> Priority_queue;
const int INF = INT_MAX;
const int MAX_N = 5000 + 5;
int N;
int DP[MAX_N][MAX_N];
 
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    string S;
    cin >> S;
    if (S.size() == 1 && S[0== '0') {
        cout << "0\n";
        return 0;
    }
    for (int i = 0; i < S.size(); i++) {
        if (S[i] == '0') {
            continue;
        }
        DP[i][i] = 1;
    }
    for (int i = 0; i < S.size() - 1; i++) {
        string temp = S.substr(i,2);
        if (S[i] == '0') {
            DP[i][i + 1= 0;
            continue;
        }
        else if (S[i + 1== '0') {
            if (stoi(temp) <= 26) {
                DP[i][i + 1= 1;
            }
            continue;
        }
        if(stoi(temp) <= 26)
            DP[i][i + 1= 2;
        else DP[i][i + 1= 1;
    }
    for (int i = 2; i < S.size(); i++) {
        DP[0][i] = DP[0][i - 1* DP[i][i];
        if (DP[i - 1][i] == 1 && stoi(S.substr(i-1,2))<= 26) {
            DP[0][i] += DP[0][i - 2];
        }
        else if(DP[i-1][i] == 2)DP[0][i] += DP[0][i - 2* (DP[i-1][i] - 1);
        DP[0][i] %= 1000000;
    }
    cout << DP[0][S.size() - 1]<< "\n";
    return 0;
}
cs

728x90