백준 9184번 신나는 함수 실행
문제
재귀 호출만 생각하면 신이 난다! 아닌가요?
다음과 같은 재귀함수 w(a, b, c)가 있다.
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)를 출력하는 프로그램을 작성하시오.
문제풀이
사용한 알고리즘 : DP
(0) 생각
문제에서 주어진 재귀 함수를 그냥 구현하면 당연히 시간이 굉장히 많이 듭니다.
따라서 a, b, c 의 각 상태에서의 함수 값을 dp로 저장해줍니다.
보통 데이터 사용량과 시간 사용량은 반비례 한다고 생각하시면 편합니다.
(1) 코드 5~6
'dp[x][y][z] : a=x, b=y, c=z 에서의 함수값' 으로 설정해주었습니다.
(2) 코드 8~18
문제에서 주어진 함수를 구현하는 함수를 만들어 주었습니다.
함수값을 dp값으로 저장해주면서 구현해주면 됩니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
int a, b, c; | |
// dp[x][y][z] : a=x, b=y, c=z 인 상태에서의 함수 값 | |
int dp[55][55][55]; | |
int DP(int x, int y, int z) { | |
if (x <= 0 || y <= 0 || z <= 0) return 1; | |
int& ret = dp[x][y][z]; | |
if (ret != -1) return ret; | |
if (x > 20 || y > 20 || z > 20) return ret = DP(20, 20, 20); | |
if (x < y && y < z) return ret = DP(x, y, z - 1) + DP(x, y - 1, z - 1) - DP(x, y - 1, z); | |
return ret = DP(x - 1, y, z) + DP(x - 1, y - 1, z) + DP(x - 1, y, z - 1) - DP(x - 1, y - 1, z - 1); | |
} | |
int main() {ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
memset(dp, -1, sizeof(dp)); | |
while (1) { | |
cin >> a >> b >> c; | |
if (a == -1 && b == -1 && c == -1) break; // 마지막 | |
cout << "w(" << a << ", " << b << ", " << c << ") = " << DP(a, b, c) << '\n'; | |
} | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!