동적 계획법은 큰 의미에서 분할 정복과 같은 접근 방식을 의미합니다. 동적 계획법을 사용하는 알고리즘들 또한 처음 주어진 문제를 더 작은 문제들로 나눈 뒤 각 조각의 답을 계산하고, 이 답들로 부터 원래 문제에대한 답을 계산해 내기 때문입니다. 이 과정에서 어떤 부분 문제는 두개 이상의 문제를 푸는데 사용될 수 있기 때문에, 이 문제의 답을 여러번 계산하는 대신 한번만 계산하고 계산 결과를 재활용함으로써 속도의 향상을 꾀할 수 있습니다.
키워드
동적 계획법은 가장 흔한 문제 유형 중 하나이기 떄문에 메모이제이션은 굉장히 자주 구현하게 된다. 따라서 한 가지 패턴을 정해두고 항상 같은 형태로 구현하도록 하자.
시간복잡도 = (존재하는 부분 문제의 수) X (한 부분 문제를 풀 때 필요한 반복문의 수행 횟수)
int solve(int x, int y) {
if (x >= N || y >= N)
return 0;
if (x == N - 1 && y == N - 1)
return 1;
int distance = board[x][y];
return solve(x + distance, y) ||solve(x, y + distance);
}
int solve(int x, int y) {
// 기저 사례를 처음에 처리한다.
if (x >= N || y >= N)
return 0;
if (x == N - 1 && y == N - 1)
return 1;
// cache 되어 있다면 곧장 반환한다.
int& ret = cache[x][y];
if (ret != -1) return ret;
// 여기서 답을 계산한다.
int distance = board[x][y];
return ret = (solve(x + distance, y) || solve(x, y + distance));
}
동적 계획법의 가장 일반적인 사용처는 최적화 문제의 해결입니다. 최적화 문제란 여러 개의 가능한 잡 중 가장 좋은 답을 찾아내는 문제를 말합니다.최적화 문제를 동적 계획법으로 푸는 것 또한 완전 탐색에서 시작합니다만, 최적화 문제에 특정 성질이 성립할 경우에는 단순히 메모이제이션을 적용하기보다 좀더 효율적으로 동적 계획법을 구현할 수 있습니다.