요구능력 : DP와 2차원 배열을 이용한 규칙
코드설명 :
계단수라고 하여서 1의 자리는 안될거 같았는데 예제보니까 됩니다.
길이가 N인 계단 수라서 N = 1이면 한자리 N = 2이면 두자리입니다.
n = 1
1, 2, 3, 4, 5, 6, 7, 8, 9
n = 2
12, 21
23, 32
34, 43
45, 54
56, 65
67, 76
78, 87
89, 98
10
여기까지만 보고 직접 n = 3일때를 맨뒷자리 기준으로 하나만 적어보면
n = 3
dp[3][3]
123
323
543
343 이 됩니다.
맨뒷자리 기준으로 봤을 때 배열을 dp[i][j]라고 하면 3앞에 2와 4는 j - 1과 j + 1이 됩니다.
그리고 2와 4의 앞에 1과 3 5와 3 또한 j - 1과 j + 1이 됩니다.
이렇게 중복되는 부분문제가 발생하기 때문에 DP로 풀 수 있는것입니다.
그리고 맨뒷자리가 3일 때 앞의 자리 숫자들 (12)3, (32)3, (54)3, (34)3 은 dp[i - 1][j -1]과 dp[i - 1][j + 1]에서 가져온것입니다.
큰 문제가 쪼개지는 DP의 특성입니다.
결론적으로, 점화식은 dp[i][j] = dp[i - 1][j + 1] + dp[i - 1][j - 1] 이 성립하게 된다.
1. dp[1]과 dp[2]를 따로 정의해준다.
2. j는 0일때와 9일때를 따로 처리해주는 이유는 0은 [j - 1]이 안되고 9는 [j + 1]이 안되기 때문이다.
후기 : 백준 15990번이 아주 도움이 많이됬다.. 규칙찾으려고 수를 나열하고 혹시나해서 맨뒤 수를 고정하고 2차원배열로 풀어봤는데 너무 쉽게 풀렸다.
let n = Int(readLine()!)! //수의 길이
var dp = Array(repeating: Array(repeating: 0, count: 10), count: 101)
var sum = 0
for i in 1...9 {
dp[1][i] = 1
}
dp[2][0] = 1
dp[2][1] = 1
dp[2][2] = 2
dp[2][3] = 2
dp[2][4] = 2
dp[2][5] = 2
dp[2][6] = 2
dp[2][7] = 2
dp[2][8] = 2
dp[2][9] = 1
for i in stride(from: 3, through: n, by: 1) {
for j in 0...9 {
if j == 0 {
dp[i][j] = dp[i - 1][j + 1] % 1000000000
}else if j == 9{
dp[i][j] = dp[i - 1][j - 1] % 1000000000
}else {
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j + 1]) % 1000000000
}
}
}
for i in 0...9 {
sum += dp[n][i]
}
print("\(sum % 1000000000)")
'Algorithm > 문제풀이_백준' 카테고리의 다른 글
[Swift][이진탐색] 백준 1920번 (수 찾기) (0) | 2021.09.02 |
---|---|
[Swift][Deque] 백준 10866번 (덱) (0) | 2021.09.01 |
[Swift][Qeque] 백준 10845번 (큐) (0) | 2021.08.31 |
[Swift][Greedy] 백준 5585번 (거스름돈) (0) | 2021.08.31 |
[Swift][DP] 백준 15990번 (1, 2, 3 더하기 5) (0) | 2021.08.31 |
댓글