728x90
https://www.acmicpc.net/problem/1463
1463번: 1로 만들기
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
www.acmicpc.net
2023.04.14 - [코딩 테스트/개념] - dynamic programming
# 1 ≤ N ≤ 10^6
import sys
readline = sys.stdin.readline
N = int(readline())
# d[n] = 숫자 n이 1이 될 때까지 필요한 연산 횟수의 최솟값
# d[i] = min(d[i // 3] + 1, d[i // 2] + 1, d[i - 1] + 1)
# 초기화: d[1] = 0
d = [0 for _ in range(N + 1)]
# bottom-up
for i in range(2, N + 1):
if i % 3 == 0 and i % 2 == 0:
d[i] = min(d[i // 3] + 1, d[i // 2] + 1, d[i - 1] + 1)
elif i % 3 == 0:
d[i] = min(d[i // 3] + 1, d[i - 1] + 1)
elif i % 2 == 0:
d[i] = min(d[i // 2] + 1, d[i - 1] + 1)
else:
d[i] = d[i - 1] + 1
print(d[N])
위 방식은 bottom-up 방식이다. 문제에서 물어보는 n이 1이 될 때까지 필요한 연산 횟수의 최솟값을 d[n]이라 정했다. 그러면 최솟값이 되는 가능한 경우가 3가지 있는데, 그 중에서 가장 작은 값을 고르면 d[n]이 된다. 일반화한 점화식은 주석에 작성했다.
top-down 방식은 아래와 같이 재귀함수로 구현할 수 있다.
# 1 ≤ N ≤ 10^6
import sys
readline = sys.stdin.readline
N = int(readline())
# d[n] = 숫자 n이 1이 될 때까지 필요한 연산 횟수의 최솟값
# d[i] = min(d[i // 3] + 1, d[i // 2] + 1, d[i - 1] + 1)
# 초기화: d[1] = 0
d = [-1 for _ in range(N + 1)]
d[1] = 0
# top-down
def find_min_count(i):
if d[i] != -1:
return d[i]
if i % 3 == 0 and i % 2 == 0:
d[i] = min(
find_min_count(i // 3) + 1,
find_min_count(i // 2) + 1,
find_min_count(i - 1) + 1,
)
elif i % 3 == 0:
d[i] = min(find_min_count(i // 3) + 1, find_min_count(i - 1) + 1)
elif i % 2 == 0:
d[i] = min(find_min_count(i // 2) + 1, find_min_count(i - 1) + 1)
else:
d[i] = find_min_count(i - 1) + 1
return d[i]
print(find_min_count(N))
728x90
'코딩 테스트 > 백준' 카테고리의 다른 글
[백준 1717번] 집합의 표현 (0) | 2023.04.14 |
---|---|
[백준 2193번] 이친수 (0) | 2023.04.14 |
[백준 11051번] 이항 계수 (0) | 2023.04.14 |
[백준 11725번] 트리의 부모 찾기 (0) | 2023.04.14 |
[백준 1197번] 최소 스패닝 트리 (0) | 2023.04.12 |