-
백준 14002번 : 가장 긴 증가하는 부분 수열 4알고리즘 공부 2020. 4. 4. 23:44
휴... 어떻게 얼기설기 풀었다. 어려운 문제일수록 뭔가 아름답게 푸는 방법이 있을 것이라는 생각이 드는데 음... 나는 사실 문제를 푸는게 우선이라서 아름다운 코드를 생각할 단계가 아니라는 생각이 든다.
아무튼 이 문제는 11053번 문제의 심화버전이다. 11053번이 단순히 길이만을 출력하는 문제라면 이 문제는 그 수열 자체를 출력해야 하는데 각 항이랑 연결된 위치를 나타내는 con이라는 수열을 추가했다. (con은 connect의 약자다)
문제의 예시를 내 코드에 적용시켜보면 그림과 같다. len이 제일 긴 녀석을 미리 저장해둔 뒤 len이 제일 긴 (예시에서는 index = 5가 제일 길기 때문에) 50에서 con을 따라 역행한다.
- con = 3이므로 index = 3인 30으로 가고
- 30의 con = 1이므로 index = 1인 20으로 간다.
- 20의 con = 0이므로 index = 0인 10으로 간다.
- 마지막으로 10의 con = -1이므로 갈 수 있는 곳이 없으므로 끝낸다.
근데 문제는 이게 역행이다보니 바로 출력하면 안된다. 그래서 이걸 출력하기 전에 어떤 vector에 적용시켜뒀다가 algorithm을 이용해 sorting을 하거나 나는 뭔가 sorting을 쓰면 O(log n)만큼의 시간이 더 걸릴 것 같아서 각각의 index를 저장해 놓은 뒤 for문을 이용해 뒤에서부터 출력했다. (애초에 역순으로 저장이 되어있으므로 뒤에서부터 출력하면 정순이다.)
#include <stdio.h> #include <iostream> #include <vector> using namespace std; int n; int seq[1004]; int len[1004]; int con[1004]; int maxLen, maxIndex; int main() { cin >> n; for(int i = 0; i <= n; i++) { cin >> seq[i]; } len[0] = 1; con[0] = -1; maxLen = 1; maxIndex = 0; for(int i = 1; i < n; i++) { len[i] = 1; con[i] = -1; for(int j = 0; j < i; j++) { if(seq[j] >= seq[i]) continue; if(len[i] > len[j] + 1) continue; len[i] = len[j] + 1; con[i] = j; } if(len[i] > maxLen) { maxLen = len[i]; maxIndex = i; } } vector<int> ansIndex; ansIndex.push_back(maxIndex); int target = maxIndex; while(con[target] != -1) { ansIndex.push_back(con[target]); target = con[target]; } int size = ansIndex.size(); cout << size << "\n"; for(int i = 1; i <= size; i++) { cout << seq[ansIndex[size - i]] << " "; } return 0; }
'알고리즘 공부' 카테고리의 다른 글
백준 1937번 : 욕심쟁이 판다 (0) 2020.04.06 백준 11054번 : 가장 긴 바이토닉 부분 수열 (0) 2020.04.06 백준 2225번 : 합분해 (0) 2020.04.03 백준 1520번 : 내리막 길 (0) 2020.04.02 백준 2167번 : 2차원 배열의 합 (0) 2020.04.01