백준 - JAVA/동적 계획법 1

[백준] 9184번 신나는 함수 실행 _ JAVA ( 주석 설명 )

wch_s 2023. 2. 16. 00:01

1번

1. 입력값 a,b,c 에 해당하는 출력값을 구분하기 위해서 dp[][][] 3차원 배열 공간을 생성한다.

2. 각 조건에 맞게 계산을 진행하고, 계산한 출력값들을 dp 에 저장한다.

3. 재귀로 함수가 다시 호출될 시, 똑같은 입력에 대한 dp 에 저장된 값이 있으면 해당 값을 사용한다. (중복 계산 줄임)

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


public class Main {
    static int[][][] dp = new int[21][21][21]; //중복 계산을 막기 위해 중간 결과값들을 저장하기 위한 배열이다.

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();

        int a = 0;
        int b = 0;
        int c = 0;

        while(true) { //-1,-1,-1 입력이 들어올 때까지 반복한다.
            st = new StringTokenizer(br.readLine());
            a = Integer.parseInt(st.nextToken());
            b = Integer.parseInt(st.nextToken());
            c = Integer.parseInt(st.nextToken());

            if(a==-1 && b==-1 && c==-1)
                break;

            //신나는 함수 실행
            sb.append("w(" + a + ", " + b + ", " + c + ") = ").append(fun(a ,b ,c)).append('\n');
        	
            /* String.format 을 이용하면 메모리와 시간 소모가 많이 된다.
            sb.append(String.format("w(%d, %d, %d) = %d", a, b, c, fun(a, b, c))).append('\n');
            */
        }

        System.out.println(sb); //입력으로 주어진 각각의 a,b,c에 대해서 fun(a,b,c)를 출력한다.
    }

    //Top-down 방식
    //Bottom-up 방식은 20*20*20의 전수조사(물론, 중간 결과값 저장으로 중복 계산이 많이 줄겠지만)를 해야하므로 비효율적이라고 예상된다.
    private static int fun(int a, int b, int c) {
        if (a <= 0 || b <= 0 || c <= 0)
            return 1;
        else if (a > 20 || b > 20 || c > 20){
            a=b=c=20;
        }
        if(dp[a][b][c]>1)
            return dp[a][b][c];

        else {
            if (a < b && b < c) {
                dp[a][b][c] = fun(a, b, c - 1) + fun(a, b - 1, c - 1) - fun(a, b - 1, c);
                return dp[a][b][c];
            }
            else {
                dp[a][b][c] = fun(a - 1, b, c) + fun(a - 1, b - 1, c) + fun(a - 1, b, c - 1) - fun(a - 1, b - 1, c - 1);
                return dp[a][b][c];
            }
        }
    }
}

1) String.format을 이용한 출력

 

2) 문자 조합을 이용한 출력