본문 바로가기
Algorithm/BOJ

[BOJ/python3] 2011번 암호코드

by DEV Lee 2021. 11. 23.

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

 

2011번: 암호코드

나올 수 있는 해석의 가짓수를 구하시오. 정답이 매우 클 수 있으므로, 1000000으로 나눈 나머지를 출력한다. 암호가 잘못되어 암호를 해석할 수 없는 경우에는 0을 출력한다.

www.acmicpc.net


문제

A를 1, B를 2, ... ,Z를 26이라 하자.

BEAN -> 25114 로 변환된다.

25114 를 문자로 다시 변환하려면  "BEAAD", "YAAD", "YAN", "YKD", "BEKD", "BEAN" 의 6가지의 경우가 나온다.

 

어떤 암호가 주어졌을 때, 그 암호 해석이 몇 가지 나올 수 있는지 구하는 프로그램

풀이

완전 DP문제이다.

현재 위치를 i라 하면, int(str(dp[i-1]) + str(dp[i]))  이 26 이하인지 확인하면 된다. 만약 해당 숫자가 26 이하이면 dp[i]=dp[i-1]+dp[i-2] 이고, 26 이상이면 dp[i]=dp[i-1] 이다.

틀렸어...

라고.....생각했는데 전혀 아니었다.

잘못 이해한 사람의 험난한 여정

무시하고 넘어간 문장이 있다.

1. 마지막 결과값에 %1000000 

2. 암호가 잘못되어 암호를 해석할 수 없는 경우에는 0을 출력

 

암호가 잘못 될 수도 있다는 뜻... -> 즉 1203 이면 12/0(무시)/3 으로 해석하는게 아니라 무조건 1/20/3 으로만 가능하단거. 문장에서 0을 무시할 수 있다는 말은 어디에도 없었다.

 

이 경우 풀이가 많이 달라진다.

0과 지금 쌍, 지난 쌍 까지 고려해서 문제를 풀어야 한다...

 

암호를 s,  s[:i] 일 때의 경우의 수를 dp[i]라 하자.

그리고 i번째 숫자를 조사한다 할 때

- 현재 위치의 두자리 숫자(int(s[i-1]+s[i]))를 num

- 바로 앞선 두자리 숫자를(int(s[i-2]+s[i-1]))를 last_num 이라 하자

 

1. 첫번째에 0이 오는 경우 return 0

2. 0이 연속 2회 이상 나오는 경우 return 0

3. s[i]가 0인 경우

     3-1.  s[i-1]이 3 이상인 경우 return 0

     3-2.  s[i-1]이 2 이하이면서, s[i-2]가 0인 경우 dp[i]=dp[i-1] 

     3-2.  last_num이 26보다 큰 경우 dp[i]=dp[i-1]

4. s[i]가 0이 아닌 경우

     4-1. i-1이 0인 경우 dp[i]=dp[i-1]

     4-2. num이 26보다 큰 경우 dp[i]=dp[i-1]

     4-3. 위 경우 둘 다 아닌 경우 dp[i]=dp[i-1]+dp[i-2]

 

이 조건을 생각하는게 너무 어려웠다

 

소스코드

def answer(s):
    if s[0] == '0':
        return 0
    if len(s) == 1:
        return 1
    
    dp = [0]*(len(s)+1)
    dp[0] = 1
    if s[1] == '0' and int(s[:2]) > 26:
        return 0
    elif( s[1] == '0' and int(s[:2]) <= 26) or int(s[:2]) > 26:
        dp[1] = 1
    else:
        dp[1] = 2
    
    for i in range(2, len(s)):
        num = int(s[i-1]+s[i])
        last_num = int(s[i-2]+s[i-1])
        
        if (s[i] == '0' and num > 26)\
            or (s[i] =='0' and s[i-1] == '0'):
            return 0
        if s[i] == '0':
            if dp[i-1] == 0 or s[i-2] == '0' or last_num > 26 :
                dp[i] = dp[i-1]
            else:
                dp[i] = dp[i-2]
        else:
            if num > 26 or s[i-1] == '0':
                dp[i] = dp[i-1]
            else:
                dp[i] = dp[i-1] + dp[i-2]
    
    return dp[len(s)-1]%1000000

s = input()
print(answer(s))

 

 

'Algorithm > BOJ' 카테고리의 다른 글

[BOJ/python3] 2231번 분해합  (0) 2021.11.29
[BOJ/python3] 11399번 ATM  (0) 2021.11.25
[BOJ/python3] 2133번 타일 채우기  (0) 2021.11.22
[BOJ/python3]3052번 나머지  (0) 2021.11.21
[BOJ/python3]2577번 숫자의 개수  (0) 2021.11.21

댓글