문제
문제 파악
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)
문제에서 이미 재귀함수가 주어지기 때문에 따로 재귀를 머리 굴려서 만들 필요가 없다.
다만, 해당 재귀를 통해 값을 구하면 매우 오래 걸린다.
여기서, 우리는 DP(Dynamic Programing)을 사용해야함을 알 수 있다.
문제 풀이
a, b, c의 값이 50까지 올 수 있기때문에 dp[51][51][51] 테이블을 선언후 dp[a][b][c]에 해당 값을 저장하면 된다.
#include<iostream>
using namespace std;
int dp[51][51][51] = { 0, };
int w(int a, int b, int c) {
if (a <= 0 || b <= 0 || c <= 0) {
return 1;
}
if (dp[a][b][c] != 0) {
return dp[a][b][c];
}
if (a > 20 || b > 20 || c > 20) {
return dp[20][20][20] = w(20, 20, 20);
}
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);
}
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() {
int a, b, c;
while (1) {
scanf("%d %d %d", &a, &b, &c);
if (a == -1 && b == -1 && c == -1) {
break;
}
printf("w(%d, %d, %d) = %d\n", a, b, c, w(a, b, c));
}
return 0;
}
주의할 점
다만, 입력과 출력을 cin, cout을 하게 될 경우 시간 초과에 걸릴 수 있다.
'문제풀이' 카테고리의 다른 글
BaekJoon(9251)::LCS (0) | 2021.12.27 |
---|---|
BaekJoon(1904)::01타일 (0) | 2021.12.16 |
BaekJoon(11053)::가장 긴 증가하는 부분 수열 (0) | 2021.12.14 |
BaekJoon(10844)::쉬운 계단 수 (0) | 2021.12.14 |
BaekJoon(1463)::1로 만들기 (0) | 2021.12.09 |