-
[백준 9095]123 더하기알고리즘/Dynamic Programming 2019. 12. 13. 10:11
Type : Dynamic Programming
접근
0부터 시작하여 1,2,3을 각각 더해 n까지 도달할 수 있는 경우를 재귀탐색 한다
f(0) -> f(0+1) + f(0+2) + f(0+3) f(1) -> f(1+1) + f(1+2) + f(1+3) f(2) -> f(2+1) + f(2+2) + f(2+3) ...
만약 n이라는 숫자가 정확하게 만들어 졌다면 true
그렇지 않다면 false를 반환 한다.일반 재귀 함수
int find(int num){ if(num == n){ return true; } if(num > n){ return false; } return find(num+1) + find(num+2) + find(num+3); }
문제에선 최대 값이 11이므로 메모이제이션을 활용하지 않아도 통과 한다
하지만 30이상이 넘어 가는 경우는 시간초과가 발생 한다주요 포인트
- 메모이제이션
- 중복되는 탐색을 없앤다
0 1 2 3 1 2 3 4 3 4 5 6
- 함수의 배열화를 통한 메모이제이션
- 1~3 까지 더하는 동안 n을 초과하지 않는 범위 내에서
- 배열에 값이 이미 들어 있다면 저장된 값을 사용 하고
- 그렇지 않다면 탐색 후 배열에 값을 저장 한다.
- 겅우의 수에 탐색 결과 혹은 배열의 값을 더한다.
for(int i = 1 ; i <= 3 ; i++){ if(num + i > n) continue; if(memo[num+i] == 0){ memo[num+i] = find(num+i); } ret += memo[num+i]; }
구현 코드
#include <iostream> #include <algorithm> #define LL long long #define MAX 100 using namespace std; int n; LL memo[MAX]; LL find(int num){ LL ret = 0; //n이 만들어 졌으므로 true 반환 if(num == n) return true; //n을 초과했으므로 false 반환 if(num > n) return false; for(int i = 1 ; i <= 3 ; i++){ if(num + i > n) continue; if(memo[num+i] == 0){ memo[num+i] = find(num+i); } ret += memo[num+i]; } return ret; } int main(void){ int t; cin>>t; for(int i = 0 ; i < t ; i++){ cin>>n; fill_n(memo, MAX, 0); cout<<find(0)<<endl; } }
깨달은 점
- 메모이제이션을 활용한 탐색의 수 줄이기
- 재귀 호출을 통해 n을 만들 수 있는 수의 조합을 찾아나갈 수 있다
'알고리즘 > Dynamic Programming' 카테고리의 다른 글
[백준 15989]1,2,3 더하기 4 (0) 2019.12.18 [백준 15988]123 더하기 3 (0) 2019.12.16 [백준 12101]123 더하기2 (0) 2019.12.16 [백준 2294] 동전 2 (0) 2019.12.10 [백준 9465] 스티커 (0) 2019.12.08