Seren dev's blog
article thumbnail

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

 

9184번: 신나는 함수 실행

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

www.acmicpc.net

1. 풀이

반복적인 재귀 호출을 방지하기 위해, w(a, b, c)의 반환값을 저장하는 3차원 dp 배열을 사용한다.

이 때 -50 ≤ a, b, c ≤ 50 이므로, 인덱스를 0부터 100까지 사용하기 위해 배열의 크기를 101x101x101만큼 할당하여 w(a, b, c)의 반환값을 dp[a+50][b+50][c+50]에 저장한다.

 

 

1.1. 로직

1. int형 3차원 배열 dp를 선언하고, 크기를 101x101x101만큼 할당한다.

2. while문을 사용하여 a, b, c를 입력받는다. (a,b,c) 가 (-1, -1, -1)인 경우 반복문을 탈출한다.

3. a, b, c 모두 50씩 더한 후 w(a, b, c)를 호출한다.

4. 출력 형식에 맞게 출력한다.

int w(int a, int b, int c)

<java />
public static int w(int a, int b, int c) { if (dp[a][b][c] != 0) return dp[a][b][c]; if (a <= 50 || b <= 50 || c <= 50) { dp[a][b][c] = 1; } else if (a > 70 || b > 70 || c > 70) { dp[a][b][c] = w(70, 70, 70); } else if (a < b && b < c) { dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c); } else { dp[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); } return dp[a][b][c]; }
  • dp[a][b][c]가 0이 아닌 경우, 이미 반환값을 구한 것이므로 바로 dp[a][b][c]를 리턴한다.
  • 문제에 나와 있는대로 함수를 구현한다. 각 경우마다 반환값을 구하고 그 값을 dp[a][b][c]에 저장한 다음 리턴한다.

2. 코드

<java />
import java.io.*; import java.util.ArrayList; import java.util.StringTokenizer; public class Main { static int[][][] dp = new int[101][101][101]; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); StringTokenizer st; while(true) { 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; bw.write("w(" + a + ", " + b + ", " + c + ") = "); a += 50; b += 50; c += 50; bw.write(w(a,b,c) + "\n"); } bw.flush(); bw.close(); br.close(); } public static int w(int a, int b, int c) { if (dp[a][b][c] != 0) return dp[a][b][c]; if (a <= 50 || b <= 50 || c <= 50) { dp[a][b][c] = 1; } else if (a > 70 || b > 70 || c > 70) { dp[a][b][c] = w(70, 70, 70); } else if (a < b && b < c) { dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c); } else { dp[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); } return dp[a][b][c]; } }

 


3. 다른 풀이 2

  • if a <= 0 or b <= 0 or c <= 0, then w(a, b, c) returns: 1 이므로 a나 b나 c가 음수인 경우는 따로 배열에 저장할 필요가 없다.
  • if a > 20 or b > 20 or c > 20, then w(a, b, c) returns: w(20, 20, 20)이므로 배열의 인덱스가 20보다 큰 경우는 따로 배열에 저장할 필요가 없다.

3.1. 코드

<java />
import java.io.*; import java.util.ArrayList; 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)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); StringTokenizer st; while(true) { 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; bw.write("w(" + a + ", " + b + ", " + c + ") = "); bw.write(w(a,b,c) + "\n"); } bw.flush(); bw.close(); br.close(); } public static int w(int a, int b, int c) { //인덱스가 배열의 범위를 벗어나지 않고, 메모이제이션이 되어있는 경우 if (checkIndexRange(a,b,c) && dp[a][b][c] != 0) return dp[a][b][c]; if (a <= 0 || b <= 0 || c <= 0) { return 1; } else if (a > 20 || b > 20 || c > 20) { return w(20, 20, 20); } else if (a < b && b < c) { dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c); } else { dp[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); } return dp[a][b][c]; } public static boolean checkIndexRange(int a, int b, int c) { if (a >= 0 && a <= 20 && b >= 0 && b <= 20 && c >= 0 && c <= 20) return true; else return false; } }

 

참고 : https://st-lab.tistory.com/190

728x90
profile

Seren dev's blog

@Seren dev

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!