문제
45656이란 수를 보자.
이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다.
N이 주어질 때, 길이가 N인 계단 수가 총 몇 개 있는지 구해보자. 0으로 시작하는 수는 계단수가 아니다.
입력
첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 100보다 작거나 같은 자연수이다.
출력
첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다.
내 풀이
n = int(input())
# dp[i][j] : 길이가 i이고 마지막 숫자가 j인 계단 수의 개수
dp = [[0]*10 for _ in range(n+1)]
for j in range(1, 10): # N = 1일 때 1~9 초기화
dp[1][j] = 1
for i in range(2, n+1):
for j in range(10):
if j == 0: # 끝자리가 0이면 1밖에 붙일 수 없음
dp[i][j] = dp[i-1][1]
elif j == 9: # 끝자리가 9이면 8밖에 붙일 수 없음
dp[i][j] = dp[i-1][8]
else: # 그 외에는 j-1, j+1의 수를 붙일 수 있음
dp[i][j] = (dp[i-1][j-1] + dp[i-1][j+1])%1000000000
print(sum(dp[n])%1000000000)
시간 복잡도 →
이중 for문이지만 내부 반복문은 10번씩만 반복됨공간 복잡도 →
2차원 배열이지만 n개의 요소를 가지고 각 요소는 10개의 요소만을 가짐
코멘트
계단 수를 구할 때 아래의 표와 같이 생각하면 좀 수월하다. 아래 표와 같이 계단 수를 만들다 보면 N = i → N = i+1 로 갈 때의 규칙을 찾을 수 있다.
(1) 0으로 끝나는 수는 뒤에 1밖에 붙일 수 없다.
ex) 10 → 101
(2) 9로 끝나는 수는 뒤에 8밖에 붙일 수 없다.
ex) 89 → 898
(3) 그 외의 수는 1 작은 수, 1 큰 수를 붙일 수 있다.
ex) 43 → 432, 434
N = 1 | N = 2 | N = 3 | |
1로 시작 | 1 | 10, 12 | 101, 121, 123 |
2로 시작 | 2 | 21, 23 | 210, 212, 232, 234 |
3으로 시작 | 3 | 32, 34 | 321, 323, 343, 345 |
4로 시작 | 4 | 43, 45 | 432, 434, 454, 456 |
5로 시작 | 5 | 54, 56 | 543, 545, 565, 567 |
6으로 시작 | 6 | 65, 67 | 654, 656, 676, 678 |
7로 시작 | 7 | 76, 78 | 765, 767, 787, 789 |
8로 시작 | 8 | 87, 89 | 876, 878, 898 |
9로 시작 | 9 | 98 | 987, 989 |
이런 규칙을 찾기도 어려웠는데 dp 배열을 구현하는 것은 더 어려웠다. 2차원 dp 배열을 이용하는 식이었다. dp[i][j]
: 길이가 N = i이고 마지막 숫자가 j인 계단 수의 개수로 정의를 하고 길이가 1인 계단 수를 초기화해둔다. 그리고 위에서 찾은 규칙을 코드로 구현하면 된다.