알고리즘

[백준] 1463번 1로 만들기 _ JAVA ( 주석 설명 ) 본문

백준 - JAVA/동적 계획법 1

[백준] 1463번 1로 만들기 _ JAVA ( 주석 설명 )

wch_s 2023. 2. 21. 04:07

1번 

→ Top-down 방식

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Main {
    static Integer[] dp; //각 숫자별로 1로 만드는 연산 횟수의 최솟값을 저장한다.
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine()); //정수 N을 입력한다.
        dp = new Integer[N+1];

        //기본값을 설정해준다.
        //dp[N]!=null이 아니게끔 하는 기본값
        dp[0] = 0;
        dp[1] = 0;
        
        System.out.println(solve(N)); //N을 1로 만드는 연산 횟수의 최솟값을 출력한다.
    }


    private static int solve(int N) {
        if(dp[N]==null) {
            //N을 1로 만드는 연산의 최솟값은
            //2로 나누는 횟수와 3을 나누는 횟수를 비교해서 그 중 작은 값을 택해야 한다.
            //N%2, N%3만큼은 -1을 하는 연산 횟수이며,
            //+1은 각 연산을 할 때마다 그 횟수를 카운팅 하기 위함이다.
            //따라서 위와 같은 점화식을 도출할 수 있다.
            dp[N] = Math.min(solve(N/2) + 1 + N%2 , solve(N/3) + 1 + N%3);
        }
        return dp[N];
    }
}

 


 

2번 

→ Bottom-up 방식

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Main {
    static Integer[] dp; //각 숫자별로 1로 만드는 연산 횟수의 최솟값을 저장한다.
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine()); //정수 N을 입력한다.
        dp = new Integer[N+1];

        //기본값을 설정해준다.
        //dp[N]!=null이 아니게끔 하는 기본값
        dp[0] = 0;
        dp[1] = 0;

        System.out.println(solve2(N)); //N을 1로 만드는 연산 횟수의 최솟값을 출력한다.
    }

    //Bottom-up 방식
    private static int solve2(int N){
        for(int i=2;i<=N;++i){
            dp[i] = Math.min(dp[i/2] + 1 + i%2, dp[i/3] + 1 + i%3);
        }

        return dp[N];
    }
}

 


 

3번 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Main {
    static Integer[] dp; //각 숫자별로 1로 만드는 연산 횟수의 최솟값을 저장한다.
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int N = Integer.parseInt(br.readLine()); //정수 N을 입력한다.
        dp = new Integer[N+1];

        //기본값을 설정해준다.
        //dp[N]!=null이 아니게끔 하는 기본값
        dp[0] = 0;
        dp[1] = 0;

        System.out.println(solve3(N)); //N을 1로 만드는 연산 횟수의 최솟값을 출력한다.
    }
    
    private static int solve3(int N){
        if(dp[N]==null) {
            if (N % 6 == 0) {
                dp[N] = Math.min(solve3(N / 3), Math.min(solve3(N / 2), solve3(N - 1))) + 1;
            } else if (N % 3 == 0) {
                dp[N] = Math.min(solve3(N / 3), solve3(N - 1)) + 1;
            } else if (N % 2 == 0) {
                dp[N] = Math.min(solve3(N / 2), solve3(N - 1)) + 1;
            }
            else{
                dp[N] = solve3(N-1) + 1;
            }
        }

        return dp[N];
    }

}