[DP] 1로 만들기PS/이코테2022. 2. 22. 22:59
Table of Contents
728x90
정수 X가 주어질 때 정수 X에 사용할 수 있는 연산은 다음과 같이 4가지이다.
a. X가 5로 나누어떨어지면, 5로 나눈다.
b. X가 3으로 나누어떨어지면, 3으로 나눈다.
c. X가 2로 나누어떨어지면, 2로 나눈다.
d. X에서 1을 뺀다.
정수 X가 주어졌을 때, 연산 4개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
예를 들어 정수가 26이면 다음과 같이 계산해서 3번의 연산이 최솟값이다.
1. 26 - 1 = 25 (4)
2. 25 / 5 = 5 (1)
3. 5 / 5 = 1 (1)
입력 조건
첫째 줄에 정수 X가 주어진다. (1 <= X <= 30,000)
출력 조건
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
정수 28을 예로 들었을 때
28 -> 27 -> 26 -> 25 -> 5 -> 1
28 -> 14 -> 7 -> 6 -> 2 -> 1
두가지 방법은 연산의 횟수가 같다. 즉 어떤 상황을 선택해야할지 판단하기 어렵다.
f(6)을 예를 들었을 때 6은 (1) 1을 빼는 연산을 수행할 수 있고 (2) 2로 나누는 연산을 수행할 수 있고 (3) 3으로 나누는 연산을 수행할 수 있다.
각 (1), (2), (3) 연산을 수행하고 나서 f(5), f(3), f(2)는 다시 가능한 연산둘로 나누어지게 된다.
따라서 정수 X가 1로 만들어진 순간부터 바텀업 방식으로 최소값을 갱신해주면 된다.
이를 주어진 예시인 26에 대입해보면 가장 빨리 끝나는 연산 방법이 f(26) -> f(25) -> f(5) -> f(1) 임을 알 수 있다.
따라서 역순인 f(1) -> f(5) -> f(25) -> f(26) 방식으로 최소값을 갱신해가면서 최소 연산의 횟수를 계산할 것이다.
# 정수 X를 입력 받기
x = int(input())
# 앞서 계산된 결과 저장하기 위한 DP 테이블 초기화
d = [0] * 30001
# 다이나믹 프로그래밍(Dynamic Programming) 진행(보텀업)
for i in range(2, x + 1):
# 현재의 수에서 1을 빼는 경우
d[i] = d[i - 1] + 1
# 현재의 수가 2로 나누어 떨어지는 경우
if i % 2 == 0:
d[i] = min(d[i], d[i // 2] + 1)
# 현재의 수가 3으로 나누어 떨어지는 경우
if i % 3 == 0:
d[i] = min(d[i], d[i // 3] + 1)
# 현재의 수가 5로 나누어 떨어지는 경우
if i % 5 == 0:
d[i] = min(d[i], d[i // 5] + 1)
print(d[x])
728x90
@TTOII :: 뭉게뭉게 클라우드
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!