문제

오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이때, 인접한 수가 같아도 오름차순으로 친다.

예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다.

수의 길이 N이 주어졌을 때, 오르막 수의 개수를 구하는 프로그램을 작성하시오. 수는 0으로 시작할 수 있다.

입력

첫째 줄에 N (1 ≤ N ≤ 1,000)이 주어진다.

출력

첫째 줄에 길이가 N인 오르막 수의 개수를 10,007로 나눈 나머지를 출력한다.

내가 푼 풀이

- 주어진 N의 길이의 오르막 수를 구하는 문제

- 오르막수는 수가 오름차순이면되고, 같은 번호여도 오름차순으로 친다.

- N이 1 일때, 앞자리수 0~9 는 모두 오르막수가 된다. 총 10개

- N이 2일때, 앞자리수와 같거나 큰수가 뒤에 올 수 있다.

앞자리수 0 1 2 3 4 5 6 7 8 9
다음 수 0~9 1~9 2~9 3~9 4~9 5~9 6~9 7~9 8~9 9
오르막 수 갯수 10개 9개 8개 7개 6개 5개 4개 3개 2개 1개

 

- N이 3일때, 마지막수는 그 전의 수보다 같거나 작아야한다.

- 예시로 00 다음에 올 수는 0~9 , 05 다음에 올 수는 5~9 가된다.

- 이는 이전 앞자리 수의 오르막 수 갯수를 모두 더한것과 같다.

앞자리수 0 1 2 3 4 5 6 7 8 9
두번째 수 (n) 0~9 1~9 2~9 3~9 4~9 5~9 6~9 7~9 8~9 9
마지막 수 n~9 n~9 n~9 n~9 n~9 n~9 n~9 n~9 n~9 n~9
오르막 수 갯수 55개 45개 36개 28개 21개 15개 10개 6개 3개 1개

 

위를 통해 규칙을 알아 낼 수 있다.

dp[i][j] = i자리수중 앞자리수가 j일때 오르막수의 갯수 라 정의하자.

dp[3][0] = 앞자리가 0인 3자리수의 오르막수 갯수

앞자리 수 0을 제외한 두번째 자리가 0으로 시작할때의 오르막수 갯수 = dp[2][0] 

앞자리 수 0을 제외한 두번째 자리가 1로 시작할때의 오르막수 갯수 = dp[2][1]

 

점화식은 dp[i][j] = dp[i][j] + dp[i-1][k] ( j <= k <= 9 )

 

위 규칙을 통해 코드로 구현했다.

import Foundation

let count = Int(readLine()!)!
var dp = Array(repeating: Array(repeating: 0, count: 10), count: count+1)
var result = 0

// 1자리 수는 오르막수도 1개
for i in 0..<10 {
    dp[1][i] = 1
}

// i자리 수에서 앞자리가 j일때 dp[i][j] += dp[i-1][k] ( j<= k <= 9 )
if count == 1 {
    result = dp[1].reduce(0 ,+)
} else {
    for i in 2...count {
        for j in 0...9 {
            for k in j...9 {
                dp[i][j] = (dp[i][j] + dp[i-1][k]) % 10007
            }
        }
    }
    result = dp[count].reduce(0, +) % 10007
}

print(result)

'코딩테스트 > 백준' 카테고리의 다른 글

BOJ-11054 가장 긴 바이토닉 부분수열 Swift  (0) 2023.05.20
BOJ-1213 팰린드롬 만들기 Swift  (0) 2023.05.18
BOJ-2293 동전 1 Swift  (0) 2023.05.18
BOJ-2437 저울 Swift  (0) 2023.05.18
BOJ-1080 행렬 Swift  (0) 2023.05.17

+ Recent posts