코딩테스트/BOJ

[BOJ] 9184 신나는 함수 실행 - JAVA

5월._. 2022. 3. 8.
728x90

1. 문제

https://www.acmicpc.net/problem/9184

 

9184번: 신나는 함수 실행

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

www.acmicpc.net

if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns:
    1

if a > 20 or b > 20 or c > 20, then w(a, b, c) returns:
    w(20, 20, 20)

if a < b and b < c, then w(a, b, c) returns:
    w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)

otherwise it returns:
    w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1)

위의 함수를 구현하는 것은 매우 쉽다. 하지만, 그대로 구현하면 값을 구하는데 매우 오랜 시간이 걸린다. (예를 들면, a=15, b=15, c=15)

a, b, c가 주어졌을 때, w(a, b, c)를 출력하는 프로그램을 작성하시오.


2. 풀이

메인함수

  • w값을 저장할 3차원 배열을 만들었다. 어차피 20이 넘어가거나 0이하이면 필요없으므로 21칸만 만들었다. (숫자를 편하게 쓰려고 메모리+1칸을 했다.) DP문제에서는 이 배열이 핵심이다. 이전값을 다시 계산할 필요 없도록 저장해놓고 다음 값에 활용하기 때문이다.
  • -1 -1 -1이 들어오기전까지 반복한다. 이 경우가 아니라면 funcW(a,b,c)를 출력한다.
static int[][][] w = new int[21][21][21];
public static void main(String[] args) throws IOException {
   BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   StringTokenizer st;
   StringBuilder sb = new StringBuilder();
   String line;

   while(!(line=in.readLine()).equals("-1 -1 -1")){
      st = new StringTokenizer(line);

      int a = Integer.parseInt(st.nextToken());
      int b = Integer.parseInt(st.nextToken());
      int c = Integer.parseInt(st.nextToken());

      sb.append("w(").append(a).append(", ").append(b).append(", ").append(c).append(") = ").append(funcW(a,b,c)).append("\n");
   }
   System.out.print(sb);
}

 

funcW - 재귀함수

  • a,b,c 중 0보다 작은 게 있다면 1을 반환한다.
  • a,b,c 중 20보다 큰 게 있다면 funcW(20,20,20)을 반환한다.
  • 만약 w[a][b][c]에 저장된 값이 있다면 그 값을 반환한다.
  • a<b<c라면 funcW(a,b,c-1)+funcW(a,b-1,c-1)-funcW(a,b-1,c) 값을 계산해서 w[a][b][c]에 넣은 후 그대로 반환한다.
  • 그 밖의 경우는 funcW(a-1,b,c)+funcW(a-1,b-1,c)+funcW(a-1,b,c-1)-funcW(a-1,b-1,c-1) 값을 계산해서 w[a][b][c]에 넣은 후 그대로 반환한다.
private static int funcW(int a, int b, int c) {
   if(a<=0 || b<=0 || c<=0) return 1;
   if(a>20 || b>20 || c>20) return funcW(20,20,20);
   if(w[a][b][c]!=0) return w[a][b][c];

   if(a<b && b<c) return w[a][b][c] = funcW(a,b,c-1)+funcW(a,b-1,c-1)-funcW(a,b-1,c);
   else return w[a][b][c] = funcW(a-1,b,c)+funcW(a-1,b-1,c)+funcW(a-1,b,c-1)-funcW(a-1,b-1,c-1);
}

3. 결과

위와 아래가 엄청나게 차이가 난다. 이유는 String.format() 함수때문이다. 자세한 이유는 이 글에서 설명했다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 2630 색종이 만들기 - JAVA  (0) 2022.03.08
[BOJ] 1003 피보나치 함수 - JAVA  (0) 2022.03.08
[BOJ] 1091 카드섞기 - JAVA  (0) 2022.02.27
[BOJ] 10158 개미 - JAVA  (0) 2022.02.27
[BOJ] 2116 주사위쌓기 - JAVA  (0) 2022.02.26

댓글