DP 알고리즘의 기초? 좋은 예제가 되는 문제인 것 같다. 유사한 형태의 DP 문제들이 있고 보고 있는 '이것이 코딩 테스트다' 에서도 유사한 문제가 있다.
DP 알고리즘에 대해 공부를 하긴 했지만 점화식을 찾는 것과 재귀를 통해 구현하는 부분이 약한 것 같아 직접 제대로 풀어봤다. 2-3시간 투자한 것 같은데.. 흠... 노력하자.
1. 바텀업 방식
- 구현하는데 매우 쉬웠다.
점화식이 d[i] = min(d[i-1], d[i // 2], d[i // 3]) + 1 로 들어온 값들을 3으로 나눌지, 2로 나눌지 아니면 1을 뺄지 구분만 잘 해준 뒤 DP 테이블에 작성해두면 된다.
주의했어야 하는 부분이 있었다.
- 조건으로 % 3, % 2 를 통해 실수값이 나올 수 없다고 생각해 dp[i / 3], dp[i / 2] 로 해서 문제가 없을 것으로 판단했지만 float 형태로 인식해 에러 발생
- // 를 사용해 확실하게 int 형으로 수정해야했다.
import sys
input = sys.stdin.readline
sys.setrecursionlimit(100000)
val = int(input())
dp = [-1] * (val+1)
dp[1] = 0
# 바텀업
for i in range(2, val+1):
dp[i] = dp[i-1] + 1 # 우선 -1을 한 걸로 초기화
if i % 3 == 0:
dp[i] = min(dp[i], dp[i//3] + 1)
# 그냥 / 를 쓰면 float 자료형으로 인식해서 // 로 확실하게 int로 만들어주기
if i % 2 == 0:
dp[i] = min(dp[i], dp[i//2] + 1)
print(dp[val])
2. 탑다운
문제 처음 봤을 때, 탑다운 방식으로 푸는 방법을 생각했다. 아이디어 방향과 접근 방식은 생각하기 쉬웠는데 구현이 어려웠다.
- 머리 아팠다
아직도 의문이 드는 부분이 있다.
3과 2의 공배수, 즉 6의 배수인 경우, 1. 3으로 나눈 경우, 2. 2로 나눈 경우, 3. 1을 뺀 경우, 총 3가지의 경우를 재귀 함수를 돌려 비교해야한다고 생각했다.
그러나 시간초과가 발생했다.
1을 뺀 경우는 고려하지 않고 돌리니 정답이었다. 사실 반례가 존재할 수도 있어서 추가해야하는 게 맞는 것 같은데 반례가 없어서 정답이 된 듯 하다.
import sys
input = sys.stdin.readline
sys.setrecursionlimit(100000)
val = int(input())
def top(value):
if dp[value] != -1:
return dp[value]
if value % 3 == 0 and value % 2 == 0:
dp[value] = 1 + min(top(value // 3), top(value // 2))
# 3으로 나눴을때, 2로 나눴을때, 1을 뺐을때, 3가지 경우를 비교해야한다고 판단
# min(top(value // 3), top(value // 2), top(value-1))을 넣으니 시간 초과 발생
elif value % 3 == 0:
dp[value] = 1 + min(top(value - 1), top(value//3))
elif value % 2 == 0:
dp[value] = 1 + min(top(value - 1), top(value // 2))
else:
dp[value] = 1 + top(value-1)
# 마지막에 value 대신 dp[value-1]을 넣어서 동작 안했음
# 1시간 동안 찾았다
return dp[value]
dp = [-1] * (val+1)
dp[1] = 0
print(top(val))
# 재귀함수는 항상 머리 아프다
# 헷갈리지만 계속 해보면서 익숙해져야함
'코딩 테스트' 카테고리의 다른 글
[백준, Hash] 1620_나는야 포켓몬 마스터 (1) | 2024.03.28 |
---|---|
[백준, 그리디] 1541_잃어버린 괄호 (0) | 2024.03.28 |
[백준, DFS/BFS]1012_유기농 배추 (1) | 2024.03.19 |
[프로그래머스 고득점 Kit] 스택_ 같은 숫자는 싫어 (0) | 2024.03.16 |
[프로그래머스 고득점 Kit] 해시_ 폰켓몬 (0) | 2024.03.13 |