뭐라도 공부해보자!!( 이론 )/자료구조 및 알고리즘
백준 10844번, 쉬운 계단 수
잡학다식을꿈꾼다
2023. 12. 4. 07:53
반응형
문제
45656이란 수를 보자.
이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다.
N이 주어질 때, 길이가 N인 계단 수가 총 몇 개 있는지 구해보자. 0으로 시작하는 수는 계단수가 아니다.
입력
첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 100보다 작거나 같은 자연수이다.
출력
첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다.
예제 입력 1
1
예제 출력 1
9
예제 입력 2
2
예제 출력 2
17
조건이 있는 다이나믹 프로그래밍 문제이다. 기본적인 골자는 k 자리수의 모든 수에 대해서 계단수를 만족하는 경우의 수를 그 이전에 구해놓은 k-1 자리 수의 모든 경우의 수로 부터 연쇄적으로 이끌어내는 것이다. 문제 조건을 충족하는 지 판단히기 위해서 모든 경우의 수를 하나로 합쳐서 저장하지 않고, k 자리 수 + 마지막 수가 0 으로 끝나는 경우, k 자리 수 + 마지막 수가 1 로 끝나는 경우, ... , k 자리 수 + 마지막 수가 9 로 끝나는 경우로 나누어 저장하였다. 나누어 저장하는 것이 이 문제를 해결하기 위한 가장 중요한 포인트이다.
나는 다음과 같이 문제를 해결하였다.
- 자릿수 N을 입력으로 받는다.
- 이중배열 cases[101][10]을 선언한다. (N의 최대값이 100 이므로...)
- N = 1인 경우에 대해 cases[1][0] ~ cases[1][9]를 채워 놓는다.
- N = 2 인 경우부터 입력값까지 연쇄적으로 배열을 채워 놓는다. 이 때 cases[k][0] = cases[k-1][1], cases[k][9] = cases[k-1][8], cases[k][j] = cases[k][j-1] + cases[k][j+1] (j = 1, 2, ..., 8) 이다. 값이 커질 경우를 위해 미리 모듈러 연산을 취해 주었다.
- 입력값에 대해서 (cases[N][0] + ... + cases[N][9]) 를 모듈러 연산을 취한 후 이를 출력한다.
코드는 다음과 같다.
#include <iostream>
#include <deque>
#define MOD 1000000000
int cases[101][10];
int main()
{
int N;
std::cin >> N;
cases[1][0] = 0;
cases[1][1] = 1;
cases[1][2] = 1;
cases[1][3] = 1;
cases[1][4] = 1;
cases[1][5] = 1;
cases[1][6] = 1;
cases[1][7] = 1;
cases[1][8] = 1;
cases[1][9] = 1;
if (N > 1)
{
for (int i = 2; i <= N; i++)
{
cases[i][0] = cases[i - 1][1];
for (int j = 1; j <= 8; j++)
{
cases[i][j] = (cases[i - 1][j - 1] + cases[i-1][j + 1]) % MOD;
}
cases[i][9] = cases[i - 1][8];
}
}
long long out = 0;
for (int i = 0; i < 10; i++)
{
out += cases[N][i];
}
std::cout << out % MOD;
return 0;
}
조건이 있는 다이나믹 프로그래밍 문제는 조건을 판단하기 위해 각 경우에 대해서도 값을 저장해 놓아야 한다는 것을 상기 시켜주는 문제였다. 이 것으로 글을 마친다.
반응형