알고리즘 공부
백준 14002번 : 가장 긴 증가하는 부분 수열 4
EQ1
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;
}