BOJ/재귀
9184번: 신나는 함수 실행
둠치킨
2025. 6. 9. 13:14
9184번: 신나는 함수 실행
사용 언어: C++
문제 요약
재귀 호출만 생각하면 신이 난다!
다음과 같은 재귀함수 w(a, b, c)가 정의되어 있다:
if a <= 0 or b <= 0 or c <= 0:
return 1
if a > 20 or b > 20 or c > 20:
return w(20, 20, 20)
if a < b and b < c:
return w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c)
else:
return 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 b c가 주어진다.
모두 -1일 경우 입력 종료.
출력:
각 입력에 대해 w(a, b, c) = 결과값 형식으로 출력한다.
문제의 함정
재귀함수 구현 자체는 쉽지만,
w(15, 15, 15) 같은 값은 수백만 번 호출되는 중복 재귀가 발생한다.
그대로 구현하면 시간 초과 혹은 시간 폭탄.
풀이
메모이제이션 (Memoization)
한 번 계산한 결과는 배열에 저장해두고
다음에 같은 입력이 오면 즉시 반환한다.
- dp[a][b][c] 배열을 사용해서 캐싱
- 입력 범위는 -50 ≤ a, b, c ≤ 50 이지만,
실제로 w()는 0 ≤ a, b, c ≤ 20까지만 캐싱하면 충분
→ a ≤ 0이면 항상 1, a > 20이면 w(20, 20, 20)로 치환되기 때문
#include <iostream>
using namespace std;
int dp[21][21][21];
int w(int a, int b, int c) {
if (a <= 0 || b <= 0 || c <= 0) return 1;
if (a > 20 || b > 20 || c > 20) return w(20, 20, 20);
if (dp[a][b][c] != 0) return dp[a][b][c];
if (a < b && b < c)
return dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c);
else
return 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);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int a, b, c;
while (true) {
cin >> a >> b >> c;
if (a == -1 && b == -1 && c == -1) break;
cout << "w(" << a << ", " << b << ", " << c << ") = "
<< w(a, b, c) << '\n';
}
return 0;
}