-
알고리즘 문제 해결 전략 - 9.7) k번째 최대 증가 부분 수열알고리즘 2021. 1. 4. 11:29
알고리즘 문제 해결 전략 책의 k번째 최대 증가 부분 수열. (동적계획법_테크닉)
기존에 풀었던 LIS문제와 달리 k번째 최대 길이 수열을 출력하는 문제였다.
#include <iostream> #include <vector> #include <cstring> #include <algorithm> #include <climits> #include <string> using namespace std; const int MAX = 2000000000 + 1;//k번째보다 1개 더 큰수 int n; int cacheLen[501], cacheCnt[501], S[500]; int lis(int start) {//S[start]에서 시작하는 증가 부분 수열 중 최대 길이를 반환 int& ret = cacheLen[start + 1];//메모이제이션 if (ret != -1) return ret; ret = 1; //항상 S[start]는 있기 때문에 최저 길이는 1 for (int next = start + 1; next < n; ++next) { if (start == -1 || S[start] < S[next]) ret = max(ret, lis(next) + 1); return ret; } } int count(int start) {//S[start]에서 시작하는 최대 증가 부분 수열의 수를 반환 if (lis(start == 1)) return 1;//LIS길이가 1인 경우 int& ret = cacheCnt[start + 1];//메모이제이션 if (ret != -1) return ret; ret = 0; for (int next = start + 1; next < n; ++next) { if ((start == -1 || S[start] < S[next]) && lis(start) == lis(next) + 1) ret = min<long long>(MAX, (long long)ret + count(next)); } return ret; } void reconstruct(int start, int skip, vector<int>& Lis) {//S[start]에서 시작하는 LIS중 사전순으로 skip개 건너띈 수열을 lis 에 저장한다. if (start != -1) Lis.push_back(S[start]);//S[start]는 항상 LIS에 포함된다 vector<pair<int, int>> followers;//뒤에 올 수 있는 숫자들과 위치의 목록을 만든다.(숫자, 숫자의 위치) for (int next = start + 1; next < n; ++next) if ((start == -1 || S[start] < S[next]) && lis(start) == lis(next) + 1)//증가수열이면 followers.push_back(make_pair(S[next], next)); sort(followers.begin(), followers.end()); for (int i = 0; i < followers.size(); ++i) { int idx = followers[i].second; int cnt = count(idx); if (cnt <= skip)//만들수 있는 갯수가 skip 보다 작다면 지나친다. skip -= cnt; else { reconstruct(idx, skip, Lis); break; } } } int main() { int c; cin >> c; for (int i = 0; i < c; i++) { int k, n; cin >> n >> k; for (int j = 0; j < n; j++) { cin >> S[j]; } memset(cacheCnt, -1, sizeof(cacheCnt)); memset(cacheLen, -1, sizeof(cacheLen)); cout << lis(-1) - 1 << endl; vector<int> Lis; reconstruct(-1, k - 1, Lis); for (int j = 0; j < Lis.size(); j++) { cout << Lis[j] << " "; } cout << endl; } return 0; }
'알고리즘' 카테고리의 다른 글
이것이 코딩테스트다 - 6) 정렬 (0) 2021.01.24 이것이 코딩테스트다 - 5) DFS/BFS (0) 2021.01.22 이것이 코딩테스트다 - 4) 구현 (0) 2021.01.21 이것이 코딩테스트다 - 3)그리디 (0) 2021.01.06 알고리즘 문제 해결 전략 - 9.6) 모스 부호 사전 (0) 2021.01.04