ALGOSPOT LIS 알고스팟 최대 증가 부분 수열
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include<iostream> #include<vector> #include<string> #include<algorithm> #include<cassert> #include<cstring> using namespace std; int n; int cache[501], S[501],C[501]; int idx; //메모제이션을 적용하기 까다로운 최대증가 부분 수열 문제를 //해결하는 완전 탐색 알고리즘 int lis(const vector<int> &A) { if (A.empty()) return 0; int ret = 0; for (int i = 0; i < A.size(); i++) { vector<int> B; for (int j = i + 1; j < A.size(); j++) if (A[i] < A[j]) B.push_back(A[j]); ret = max(ret, 1 + lis(B)); } return ret; } //S[start]에서 시작하는 증가 부분 수열 중 최대 길이를 반환한다. int lis2(int start) { int&ret = cache[start]; if (ret != -1) return ret; //항상 S[start]는 있기 때문에 길이는 최하 1 ret = 1; for (int next = start + 1; next < n; next++) if (S[start] < S[next]) ret = max(ret, 1 + lis2(next)); return ret; } //lis2함수에서 main에서 for문을 적용시키기 귀찮을 때 int lis3(int start) { int &ret = cache[start + 1]; if (ret != -1) return ret; //항상 S[start]는 있기 때문에 길이는 최하 1 ret = 1; for (int next = start + 1; next < n; next++) if (start == -1 || S[start] < S[next]) ret = max(ret, 1 + lis3(next)); return ret; } void lis4(int num) { if (idx == 0 || (idx > 0 && C[idx - 1] <= num)) //해당 숫자가 더 크거나 벡터가 비어있다면 { C[idx++] = num; return; } //증가 부분 순열에 성립하지 않은 숫자라면 삽입할 위치를 찾는다 int front = 0; int rear = idx - 1; while (front <= rear) //이진탐색 { int mid = (front + rear) / 2; if (C[mid] < num) front = mid + 1; else rear = mid - 1; } C[rear + 1] = num; } int main(){ int cases; cin >> cases; while (cases--) { cin >> n; vector<int> A; for (int i = 0; i < n; i++) { cin >> S[i]; A.push_back(S[i]); } cout << lis(A) << " LIS1" << endl; memset(cache, -1, sizeof(cache)); int maxLen = 0; for (int i = 0; i < n; i++) { maxLen = max(maxLen, lis2(i)); } cout << maxLen <<" LIS2" <<endl; memset(cache, -1, sizeof(cache)); //가상으로 추가 입력한 값이 있으므로 //cache[]의 크기가 1커졌으므로 최종 반환값에서 빼주기 cout << lis3(-1) - 1 << " LIS3"<< endl; memset(C, 0, sizeof(C)); idx = 0; for (int i = 0; i < n; i++) lis4(S[i]); cout << idx << " LIS4" << endl; } return 0; } | cs |
문제 출처:https://algospot.com/judge/problem/read/LIS
lis4 함수 사용 방법은 생각도 못했네요. 신기합니다.
'알고리즘 > 알고리즘 문제 해결전략(종만북)' 카테고리의 다른 글
ALGOSPOT PI 알고스팟 파이 (0) | 2019.01.23 |
---|---|
ALGOSPOT JLIS 알고스팟 합친 LIS (0) | 2019.01.23 |
ALGOSPOT TRIANGLEPATH 알고스팟 삼각형 위의 최대 경로 (0) | 2019.01.22 |
ALGOSPOT WILDCARD 알고스팟 와일드카드 (2) | 2019.01.22 |
Sorting Game 29장 SORTGAME (0) | 2019.01.07 |