백준 - 2011

아따맘마·2021년 1월 8일
0

알고리즘 - 백준

목록 보기
29/53

문제

상근이와 선영이가 다른 사람들이 남매간의 대화를 듣는 것을 방지하기 위해서 대화를 서로 암호화 하기로 했다. 그래서 다음과 같은 대화를 했다.

  • 상근: 그냥 간단히 암호화 하자. A를 1이라고 하고, B는 2로, 그리고 Z는 26으로 하는거야.
  • 선영: 그럼 안돼. 만약, "BEAN"을 암호화하면 25114가 나오는데, 이걸 다시 글자로 바꾸는 방법은 여러 가지가 있어.
  • 상근: 그렇네. 25114를 다시 영어로 바꾸면, "BEAAD", "YAAD", "YAN", "YKD", "BEKD", "BEAN" 총 6가지가 나오는데, BEAN이 맞는 단어라는건 쉽게 알수 있잖아?
  • 선영: 예가 적절하지 않았네 ㅠㅠ 만약 내가 500자리 글자를 암호화 했다고 해봐. 그 때는 나올 수 있는 해석이 정말 많은데, 그걸 언제 다해봐?
  • 상근: 얼마나 많은데?
  • 선영: 구해보자!

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

입력

첫째 줄에 5000자리 이하의 암호가 주어진다. 암호는 숫자로 이루어져 있다.

출력

나올 수 있는 해석의 가짓수를 구하시오. 정답이 매우 클 수 있으므로, 1000000으로 나눈 나머지를 출력한다.

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

풀이

일단 암호가 잘못된 경우는 딱 한가지 있다. 맨 앞자리가 0일 경우.
그래서 바로 str[0] == 0 이면 0을 출력하고 끝낸다.
맨 처음 이문제를 접했을 때 너무 복잡하게 생각해서 해맸었다. 그러다가 구글링하면서 메커니즘을 보니까 바로 풀 수 있었다.
기본적으로 DP[0] = 1로 초기화.

  • str[i] == 0 인 경우(맨 앞자리가 아니고)
    이 경우는 이 한자리로는 알파벳으로 변환할 수 없기 때문에, 이 전 자리와 결합해야 한다. 따라서 DP[i] += DP[i - 2]; 이다.
    DP[i - 2]경우에서 str[i-1] * 10 + str[i]인 경우 하나를 더한 것이기 때문이다.
    여기서도 예외가 있는데 숫자가 10 <= num <= 26 의 범위를 가져야 한다.
  • str[i]가 0~9까지의 숫자일 경우
    일단 str[i]는 바로 알바펫으로 변환이 가능하여, DP[i] += DP[i-1]이다. 그리고 만약 전 자리의 수와 결합해서 10 ~ 26 사이에 존재하는 숫자이면
    DP[i] += DP[i-2]도 가능하다.

코드

#include <iostream>
#include <string>
#define MOD 1000000
using namespace std;

int main() {
	string str;
	long long DP[5001] = { 0, };
	int tmp;
	int j;

	cin >> str;
	DP[0] = 1;
	for (int i = 0; i < str.length(); i++)
	{
		j = i + 1;
		if (str[0] == '0')
		{
			cout << 0;
			return (0);
		}
		if (str[i] >= '1' && str[i] <= '9')
			DP[j] += DP[j - 1];
		if (i != 0)
		{
			tmp = (str[i - 1] - '0') * 10 + (str[i] - '0');
			if (tmp >= 10 && tmp <= 26)
				DP[j] += DP[j - 2];
		}
		DP[j] %= MOD;
	}
	cout << DP[str.length()] % MOD;
}
profile
늦게 출발했지만 꾸준히 달려서 도착지점에 무사히 도달하자

0개의 댓글

관련 채용 정보