정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.
a. X가 3으로 나누어 떨어지면, 3으로 나눈다.
b. X가 2로 나누어 떨어지면, 2로 나눈다.
c. 1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.
첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.
첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
다이나믹 프로그래밍(DP) 를 사용해서 풀 수 있는 문제다.
다이나믹 프로그래밍 같은 경우 탑다운 방식과 바텀업 방식 두 가지가 있는데 이번 문제에서는 바텀업 방식을 사용해서 풀었다.
가장 큰 수로 나누면 되는게 아니라 연산을 사용하는 횟수의 최솟값을 구해야하기 때문에 모든 경우의 수를 다 시도해 봐야 한다.
2부터 시작해 입력 받은 숫자까지 for 문을 돌면서 해당 값을 구할 수 있는 가장 최솟값을 구하고, 그 값을 바탕으로 다음 최솟값을 구하는 방식으로 풀었다.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int min_count[] = new int[x+1];
// DP 의 Bottom-up 방식 사용
for (int i = 2; i <= x; i++) {
// 1 로 빼는 경우
min_count[i] = min_count[i - 1] + 1;
// 2로 나누어 떨어지는 경우
if (i % 2 == 0) min_count[i] = Math.min(d[i], min_count[i / 2] + 1);
// 3으로 나누어 떨어지는 경우
if (i % 3 == 0) min_count[i] = Math.min(d[i], min_count[i / 3] + 1);
}
System.out.println(d[x]);
}
}