15988번: 1, 2, 3 더하기 3
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
www.acmicpc.net
아이디어:
DP를 활용하여 생각해보면 1, 2, 3으로 나눌 수 있으므로
i 번째 숫자 = i-1번 숫자에서 1을 더한 경우 + i-2번 숫자에서 2를 더한 경우 + i-3번 숫자에서 3을 더한 경우 로 구할 수 있다.
따라서 dp를 만들어서 dp[i] = dp[i-1]+dp[i-2]+dp[i-3] 으로 푼다.
틀린 부분:
앞선 피보나치 문제처럼 재귀함수를 만들어서 풀 수 있지 않을까 하고 구현해보았는데 시간 초과가 났다.
#시간초과
import sys
sys.setrecursionlimit(1000009)
t = int(sys.stdin.readline())
dp = [0 for _ in range(1000001)]
dp[1]=1 #1
dp[2]=2 #2, 1+1
dp[3]=4 #3, 1+2, 2+1, 1+1+1
def solve(i):
if (dp[i]!=0):
return dp[i]
else:
dp[i] = solve(i-1) + solve(i-2) + solve(i-3)
dp[i] %= 1000000009
return dp[i]
for _ in range(t):
n = int(sys.stdin.readline())
print(solve(n))
문제 풀이에서는 아예 주어진 n의 범위까지 모두 반복문으로 한 번에 구한 후 dp[n]을 출력하는 방식으로 풀더라. 이건 통과한다. 아무래도 재귀함수로 푸는 경우에는 dp를 사용하더라도 그 깊이가 깊어지면 시간이 많이 소요되는 것 같다. 게다가 이 문제에서는 1000을 구하고 다시 1001을 구할 때 1000번만큼의 비교를 다시 해야하니까 재귀로 구현하는 것이 아주 비효율적이다.
#통과한 답
import sys
t = int(sys.stdin.readline())
dp = [0 for _ in range(1000001)]
dp[1]=1 #1
dp[2]=2 #2, 1+1
dp[3]=4 #3, 1+2, 2+1, 1+1+1
for i in range(4,1000001):
dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
dp[i] %= 1000000009
for _ in range(t):
n = int(sys.stdin.readline())
print(dp[n])
'알고리즘💻 > DP' 카테고리의 다른 글
BOJ 14494번: 다이나믹이 뭐예요? (0) | 2021.01.24 |
---|---|
BOJ 20500번: Ezreal 여눈부터 가네 ㅈㅈ (0) | 2021.01.24 |
BOJ 1463번: 1로 만들기 (0) | 2021.01.24 |
BOJ 1757번: 달려달려 (0) | 2021.01.24 |
BOJ 2748번: 피보나치 수 2 (0) | 2021.01.24 |
15988번: 1, 2, 3 더하기 3
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
www.acmicpc.net
아이디어:
DP를 활용하여 생각해보면 1, 2, 3으로 나눌 수 있으므로
i 번째 숫자 = i-1번 숫자에서 1을 더한 경우 + i-2번 숫자에서 2를 더한 경우 + i-3번 숫자에서 3을 더한 경우 로 구할 수 있다.
따라서 dp를 만들어서 dp[i] = dp[i-1]+dp[i-2]+dp[i-3] 으로 푼다.
틀린 부분:
앞선 피보나치 문제처럼 재귀함수를 만들어서 풀 수 있지 않을까 하고 구현해보았는데 시간 초과가 났다.
#시간초과
import sys
sys.setrecursionlimit(1000009)
t = int(sys.stdin.readline())
dp = [0 for _ in range(1000001)]
dp[1]=1 #1
dp[2]=2 #2, 1+1
dp[3]=4 #3, 1+2, 2+1, 1+1+1
def solve(i):
if (dp[i]!=0):
return dp[i]
else:
dp[i] = solve(i-1) + solve(i-2) + solve(i-3)
dp[i] %= 1000000009
return dp[i]
for _ in range(t):
n = int(sys.stdin.readline())
print(solve(n))
문제 풀이에서는 아예 주어진 n의 범위까지 모두 반복문으로 한 번에 구한 후 dp[n]을 출력하는 방식으로 풀더라. 이건 통과한다. 아무래도 재귀함수로 푸는 경우에는 dp를 사용하더라도 그 깊이가 깊어지면 시간이 많이 소요되는 것 같다. 게다가 이 문제에서는 1000을 구하고 다시 1001을 구할 때 1000번만큼의 비교를 다시 해야하니까 재귀로 구현하는 것이 아주 비효율적이다.
#통과한 답
import sys
t = int(sys.stdin.readline())
dp = [0 for _ in range(1000001)]
dp[1]=1 #1
dp[2]=2 #2, 1+1
dp[3]=4 #3, 1+2, 2+1, 1+1+1
for i in range(4,1000001):
dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
dp[i] %= 1000000009
for _ in range(t):
n = int(sys.stdin.readline())
print(dp[n])
'알고리즘💻 > DP' 카테고리의 다른 글
BOJ 14494번: 다이나믹이 뭐예요? (0) | 2021.01.24 |
---|---|
BOJ 20500번: Ezreal 여눈부터 가네 ㅈㅈ (0) | 2021.01.24 |
BOJ 1463번: 1로 만들기 (0) | 2021.01.24 |
BOJ 1757번: 달려달려 (0) | 2021.01.24 |
BOJ 2748번: 피보나치 수 2 (0) | 2021.01.24 |