본문 바로가기

Java/백준

[JAVA] 백준 9184 신나는 함수 실행

9184번: 신나는 함수 실행 (acmicpc.net)

 

9184번: 신나는 함수 실행

입력은 세 정수 a, b, c로 이루어져 있으며, 한 줄에 하나씩 주어진다. 입력의 마지막은 -1 -1 -1로 나타내며, 세 정수가 모두 -1인 경우는 입력의 마지막을 제외하면 없다.

www.acmicpc.net

 

재귀 함수 w(a,b,c)

 

- a,b,c가 주어졌을 때 w(a,b,c)를 출력하는 프로그램 

 

 

풀이 과정 

 

 

동적 프로그램(DP, 동적 계획법)

 

[Algorithm] 동적 프로그래밍 (DP, 동적 계획법) 이해하기 (+ 예제 코드) (tistory.com)

 

[Algorithm] 동적 프로그래밍 (DP, 동적 계획법) 이해하기 (+ 예제 코드)

인트로 +컴퓨터공학을 전공하셨거나 코딩 테스트를 준비하시는 분들은 한 번쯤 접해보셨을 동적 프로그램(DP, 동적 계획법)을 쉽게 이해하기 위해 작성한 글입니다. ★ 동적 프로그래밍은 "큰 문

kangworld.tistory.com

 

- "큰 문제"를 "부분 문제"로 나누고 "부분 문제"의 정답으로 "큰 문제"의 해답을 찾아가는 알고리즘 설계 기법 

- 동적 프로그래밍은 분할 정복이 동일하다고 생각할 수 있지만 해를 구하기 위해 쪼갠 "부분 문제"의 특성이 다르다 

- "큰 문제"를 찾기 위해 여러 "부분 문제"를 반드시 풀어야 하고 "부분 문제"는 반드시 중복해서 나타남

 

- 중복되는 부분 문제(Overlapping Subproblem)는 분할 정복과 동적 프로그래밍의 가장 큰 차이 

- 분할 정복은 "큰 문제"가 "유니크한 부분 문제"로 나뉘지만 동적 프로그래밍은 "부분 문제"가 반복적으로 등장 

 

- "큰 문제"의 해를 찾기 위한 연산과 "부분 문제"의 해를 찾기 위한 연산이 동일해야 하며 "부분 문제"의 해를 조합해 "큰 문제"의 해를 찾을 수 있는 구조를 최적 부문 구조(Optimal Substructure)라고 함

- "큰 문제"의 해는 "부분 문제"의 조합으로 찾을 수 있으며 문제의 해는 동일한 연산으로 수행되어야 함 

 

- 동적 프로그래밍에선 중복된 계산을 피하고자 이전에 구한 "부분 문제"의 해를 메모리에 저장해두며 이를 메모이제이션(Memoization)이라고 함 

 

 

- 메모이제이션을 활용한 재귀로 풀이 

- memo[][][]에 저장한 값이 0이 아니라면 이미 계산된 문제 이므로 그 값을 리턴 

- 조건에 맞춰 연사을 수행한 후 , 그 결과값을 memo[][][]에 저장 후 리턴 

 

 

정답 

 

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

public class Main {
    static int memo[][][] = new int[21][21][21];
    
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        StringBuilder sb = new StringBuilder();
        
        while(true)
        {
            StringTokenizer st = new StringTokenizer(br.readLine());
            
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            
            
            if(a==-1&&b==-1&&c==-1)
                break;
            
            sb.append("w(" + a + ", " + b + ", " + c + ") = ").append(w(a ,b ,c)).append('\n');
        }
        
        
        System.out.println(sb);
    }
    
    static int w(int a,int b,int c)
    {
        if(check(a,b,c)&& memo[a][b][c] !=0)
        {
            return memo[a][b][c];
        }
        
        if(a<=0||b<=0||c<=0)
        { 
             return 1;
        }
        
        if(a>20||b>20||c>20)
        {
            return memo[20][20][20] = w(20,20,20);
        }
        
        if(a<b&&b<c)
        {
            return memo[a][b][c] = w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
        }
        
        return memo[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
 
    }
    
    //범위 조건
    static boolean check(int a,int b,int c)
    {
        return 0<=a && a<=20 && 0<=b && b<=20&& 0<=c && c<=20;
    }
}

 

 

'Java > 백준' 카테고리의 다른 글

[JAVA] 백준 9461 파토반 수열  (0) 2024.02.26
[JAVA] 백준 1904 01타일  (0) 2024.02.26
[JAVA] 백준 14889 스타트와 링크  (0) 2024.02.26
[JAVA] 백준 2580 스도쿠  (0) 2024.02.23
[JAVA] 백준 9663 N-Queen  (0) 2024.02.23