유형: 동적프로그래밍
작성일시: 2022년 11월 26일 오후 12:20
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 2 | 3 | 2 | 3 | 3 | 2 | 3 |
정수 X에 대한 연산
→ 정수 N이 주어졌을 때, 위의 연산 세 개를 적절히 사용해 1을 만든다. 연산을 사용하는 횟수의 최솟값을 출력한다.
# 입력 1 2 # 출력 1 10
# 입력 2 1 # 출력 2 3
먼저 나열해본다.
ex) n = 10
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 2 | 3 | 2 | 3 | 3 | 2 | 3 |
열거함으로써 규칙성을 발견했다.
하지만 예외 존재!
📢 ex) 10, 15
위에서 나열했을 때, 10의 값은 2로 나눈 값이 아니라 먼저 -1을 빼야 최소횟수가 나온다.
10 : 10-1, 9/3, 3/3(3) or 10/2, 5-1, 4/2, 2/2 (4)
하지만 15의 경우는 먼저 1을 뺀 것이 아니라 3으로 나누고 나서 연산하는 것이 최소횟수가 나온다.
15 : 15-1, 14/2, 7-1, 6/3, 2/2 (5) or 15/3, 5-1, 4/2, 2/2 (4)
⇒ 따라서, 무조건적으로 -1을 먼저 연산하거나, 나누기 연산을 먼저 하는 것이 아니라, 두 연산 모두 거친 후 둘 중의 최솟값을 비교하는 방식으로 가야 한다. (min함수 사용)
→ 각각의 테이블에는 해당 인덱스의 숫자가 1이 된다. 이 1이 되는데 필요한 연산의 수가 저장된다.
index (1~n) | 1 | 2 | 3 | … | n |
---|---|---|---|---|---|
최소 턴 개수 |
Bottom Up 방식
n = int(input()) # 수 입력 받기
dp = [0] * (n+1) #dp 리스트 초기화
for i in range(2, n+1): #2부터 n까지 반복
dp[i] = dp[i-1] + 1 #1을 빼는 연산 (1회 진행)
if i % 3 == 0: # 3으로 나누어 떨어질 때, 3으로 나누는 연산
dp[i] = min(dp[i], dp[i//3]+1)
if i % 2 == 0: #2로 나누어 떨어질 때, 2로 나누는 연산
dp[i] = min(dp[i], dp[i//2]+1)
print(dp[n]) #출력
n
에 입력 받는다dp리스트
에 0이 n+1
개 있는 리스트로 초기화한다for i in range (2, n+1)
: 2부터 n까지 i로 반복한다.dp[i] = dp[i-1] + 1 : dp[1]
는 숫자가 i가 1이 되는데 걸리는 최소한의 연산횟수를 저장해야 한다.dp[i-1]
(i=1이 1이 되는데 필요한 최소한의 연산) + 1
(i에서 1을 빼서 i-1이 되는데 필요한 연산 횟수 1회)로 초기화한다.**if i % 3 == 0: dp[i] = min(dp[i], dp[i//3]+1)**
:: i가 3으로 나누어 떨어질 때, dp[i]
와 dp[i//3] + 1
중 최솟값을 dp[i]에 저장한다.dp[i//3]+1
은 i를 3으로 나눈 값이 1이 되는데 걸린 최소 연산횟수 + i를 3으로 나눈 연산횟수 1회이다.if i%2==0: d[i]=min(d[i],d[i//2]+1)
[백준] 1463 1로 만들기 (DP) - Python / 자세한 설명 / 여러가지 풀이 / 실버1