백준 1463_1로 만들기 / Python

2023. 8. 28. 01:06백준

문제

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

  1. X가 3으로 나누어 떨어지면, 3으로 나눈다.
  2. X가 2로 나누어 떨어지면, 2로 나눈다.
  3. 1을 뺀다.

정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

입력

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

출력

첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

예제 입력 1 복사

2

예제 출력 1 복사

1

예제 입력 2 복사

10

예제 출력 2 복사

3

힌트

10의 경우에 10 → 9 → 3 → 1 로 3번 만에 만들 수 있다.


이 문제는 dp문제랜다...그게 몬데.

 

DP: Dynamic Programming. 

1. 큰 문제를 작은 문제로 나눌 수 있다.

2. 작은 문제에서 구한 정답이 그것을 포함하는 큰 문제에서도 동일하다.

 

이 문제에 적용해 보자..

만약 12를 1로 만들기 위한 최소횟수를 구하려면

12에서 1 빼기/2로 나누기/3으로 나누기 총 3가지의 경우의 수를 모두 구한 다음 셋 중 최소값에 +1 해주면 됨.

*+1해주는 이유. 3가지의 경우의 수를 적용해 보는게 일단 횟수 1번이기 때문!

즉, 12-1, 12//2, 12//3 이 1이 되는 최소횟수를 구해서 최소값+1해주면 12가 1되는 최소횟수임.

 

 

우선 입력값이 1 이상이라 dp[0]에는 아무거나 넣어줌.

1이 1이 되려면 아무것도 필요없음. dp[1]=0

2가 1이 되려면 //2 한 번. dp[2]=1

3이 1이 되려면 //3 한 번. dp[3]=1

 

4부터는 DP공식을 이용해서 구함.(4부터 n+1까지 for문 반복. dp[n]을 구해야하기 때문.)

a,b,c에 세가지 연산에 대한 경우의 수를 담고 최소값 찾은 후 +1 하여 dp에 append해주기.

*//2랑 //3은 나누어떨어질때만 해줘야하고 최소값으로 채택되면 안되기 때문에 입력값의 최대값인 100000으로 매번 초기화하기.

import sys
n=int(sys.stdin.readline().rstrip())
dp=[None, 0, 1, 1] 

if n>=4:
  for i in range(4,n+1):
    a,b,c=100000, 100000, 100000
    a=dp[i-1]
    if i%2==0:
      b=dp[i//2]
    if i%3==0:
      c=dp[i//3]
    dp.append(min(a,b,c)+1)
  print(dp[n])
else:
  print(dp[n])