문제 설명
문제
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 3가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 단, 같은 수를 두 번 이상 연속해서 사용하면 안 된다.
- 1+2+1
- 1+3
- 3+1
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 100,000보다 작거나 같다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
풀이 과정
- DP 테이블을 구성한다
- DP[i][j] : i를 합으로 나타낼 때, 맨 마지막에 사용할 수가 j
- DP 테이블의 값을 미리 모두 채워둔다.
- 최대 N이 100000이므로 100000개 모두 미리 채워둔다.
- DP[i][1]의 값은 DP[i-2][2] + DP[i-3][3] 이러한 식으로 채워줌.
- 이유는, 1을 사용하기 위해서는 이전에 2 또는 3이 나타나야 하기 때문.
- 어려웠던 점
- DP 테이블을 2차원으로 구성해야 되는 점 생각이 어려웠음..
- DP 테이블을 반복문에서 매번 초기화해줘서 시간 초과가 나타났는데, 이 점을 맨 위에서 모두 채워주고 아래에서 테스트 케이스를 입력받을 때, 대응되는 값을 바로바로 출력하도록 바꾸어 줌.
소스 코드
import sys
input = sys.stdin.readline
T = int(input().rstrip())
# dp[i][j] : i번째에 마지막으로 숫자가 j인 경우
dp = [[0, 1, 1, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 1, 1]] + (
[[0] * 4 for _ in range(100001)]
)
for i in range(4, 100001):
for j in [1, 2, 3]:
for k in range(1, 4):
# 이전에 나온 숫자를 바로 다시 나오게 하면 안됨.
if j != k:
dp[i][j] = (dp[i][j] + dp[i-j][k]) % 1000000009
for _ in range(T):
n = int(input().rstrip())
print(sum(dp[n]) % 1000000009)
'알고리즘[Python] > 백준 알고리즘' 카테고리의 다른 글
[ 5427 ] [ BFS ] 불 (0) | 2021.09.02 |
---|---|
[ 11660 ] [ DP ] 구간 합 구하기 5 (0) | 2021.09.01 |
[ 11057 ] [ DP ] 오르막 수 (0) | 2021.08.31 |
[ 2230 ] [ Two-Pointer ] 수 고르기 (0) | 2021.08.31 |
[ 10972 ] [ 순열 ] 다음 순열 (0) | 2021.08.30 |