※ 웹 환경에 최적화된 서식이므로 웹 페이지로 열람함을 권장.
최대 증가 부분 수열(링크)
각 원소로부터 출발한 재귀함수에서 해당 원소보다 뒤에 있는 원소 중 더 큰 것들만 골라 다시 재귀에 진입한다. 부분 수열을 가지고 재귀하지 않고 현재 Index 를 함수의 입력으로 한다.
즉, 현재 원소보다 큰 다음 원소의 Index 를 재귀로 입력한다. (다음에 선택될 원소는 항상 이전 원소보다 크므로 항상 모든 큰 값을 가지는 부분 수열을 재귀의 입력으로 줄 필요 없다.)
어떤 위치의 원소에 대해 다음으로 선택할 원소는 이전에 선택했던 원소와 관계없이 일정하므로 최적 부분 구조를 가지는 문제이다. (어떤 위치에서의 최적의 결과는 이전의 선택과 무관하게 일정.)
따라서, 현재 함수에 진입하는 Index 에 대한 결과값만을 저장해서 Memoization하면 동적 계획으로 해결할 수 있다.
#include <iostream>
#include <vector>
using namespace std;
int len;
int cache[500];
vector<int> seq;
int lisMemoization(int start) {
int& ret = cache[start];
if (ret != -1) return ret;
// lis starts from each element so they have minimum length of 1.
ret = 1;
for (int next = start + 1; next < seq.size(); ++next) {
if (seq[start] < seq[next])
ret = max(ret, lisMemoization(next) + 1);
}
return ret;
}
// LIS Starts from all of the index.
int startLIS() {
int ret = 0;
for (int i = 0; i < seq.size(); ++i)
ret = max(ret, lisMemoization(i));
return ret;
}
int main() {
int C; cin >> C;
vector<int> answers;
while (C-- > 0) {
memset(cache, -1, sizeof(cache));
cin >> len;
int n;
for (int i = 0; i < len; ++i) {
cin >> n;
seq.push_back(n);
}
answers.push_back(startLIS());
seq.clear();
}
for (const auto& e: answers) cout << e << endl;
return 0;
}
'문제 해결 알고리즘 기초 > 동적 계획' 카테고리의 다른 글
[알고스팟] 원주율 외우기 - 동적 계획, 최적 부분 구조 (0) | 2021.05.07 |
---|---|
최적해 문제를 동적 계획법으로 구하는 순서 (0) | 2021.05.04 |
동적 계획과 최적화 문제, Triangle Path(알고스팟) (0) | 2021.04.27 |
[알고스팟] Wild Card - 동적 계획 (0) | 2021.04.21 |
[알고스팟] Jump Game - 동적 계획, 메모이제이션 (0) | 2020.09.28 |