백준

백준 1463번 1로 만들기 (java)

대기업 가고 싶은 공돌이 2024. 8. 25. 22:33

[Silver III] 1로 만들기 - 1463

문제 링크

성능 요약

메모리: 79372 KB, 시간: 216 ms

분류

다이나믹 프로그래밍

제출 일자

2024년 8월 25일 22:25:49

문제 설명

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

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

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

입력

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

출력

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

 

풀이

다이나믹 프로그래밍으로 한 번 풀어봤다.

 

다이나믹 프로그래밍이란 이전의 결과를 저장하고 다음 함수에 사용함으로써, 시간 복잡도를 줄이는 방법이다.

 

계산 방식은 총 세 가지다 

 

  1. 3으로 나누기
  2. 2로 나누기
  3. 1을 빼기

우리가 코드를 짜며 생각해야할 부분은

 

3과 2 동시에 나눠질 때 분기를 어떻게 나눌 것인가,

 

3으로 나눠질 때의 분기를 어떻게 나눌 것인가,

 

2로 나눠질 때 분기를 어떻게 나눌까 이다.

 

6으로 나눠 떨어진다면

 

3으로 나눴을 때 수행 횟수 VS 2로 나눴을 때 수행 횟수 VS -1을 했을 때 수행 횟수를 비교하면 될 것이다.

 

이와 마찬가지로 다른 분기에도 모두 적용을 시키고 코드를 짜보면 다음과 같이 코드를 작성할 수 있다.

 

전체 코드

public class Main {
    public static void main(String args[])throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int N = Integer.parseInt(br.readLine());
        int[] dp = new int[N+1];

        for(int  i = 0 ;i<=N;i++){
            dp[i] = -1;
        }
        dp[0] = dp[1] = 0;
        int k = cur(N,dp);

        bw.write("" + k);
        bw.flush();


    }

    public static int cur(int N, int dp[]){
        if(dp[N] == -1) {
            if(N % 6 == 0){
                dp[N] = Math.min(cur(N/3,dp), Math.min(cur(N/2,dp), cur(N-1,dp)))+1;
            }
            else if (N % 3 == 0) {
                dp[N] = Math.min(cur(N-1,dp),cur(N / 3, dp))+1;
                return dp[N];
            } else if (N % 2 == 0) {
                dp[N] = Math.min(cur(N/2,dp),cur(N-1,dp))+1;
                return dp[N];
            }
            else{
                dp[N] = cur(N-1,dp)+1;
                return dp[N];
            }
        }
        return dp[N];
    }

}