📗 CS/Algorithm

[DP] 11053. 가장 긴 증가하는 부분 수열 4

Dongwoongkim 2023. 9. 12. 20:23

 

문제

수열 A가 주어졌을 때 가장 긴 증가하는 부분수열의 길이와 부분수열을 출력하는 문제.

증가 수열의 길이는 DP를 이용하여 쉽게 구할 수 있습니다.

 

 

 

우선 증가수열의 길이부터 구해봅시다.

 

1. dp 배열 값을 모두 1로 초기화 합니다.

: v 배열에서 모든 인덱스의 배열값은 증가 수열의 시작이 될 수 있기 때문에 1로 초기화 해줍니다.

 

 

2. 0번째부터 n-1번째 까지 이중 포문으로 현재 인덱스 위치의 값보다 다음 인덱스 위치(j번째)의 값이 더 크다면

dp 배열의 j번째 값과, i번째 값 + 1중 큰 값을 dp배열의 j번째 값에 삽입합니다.

 

 

3. 가장 긴 증가하는 부분 수열을 출력

 

dp 배열을 이용하여 역추적하여 증가하는 부분수열을 쉽게 구할 수 있습니다.

역추적하지 않고 dp값이 1인 배열부터 순서대로 가장 큰 길이인 4까지 가는 방법도 있지만,
추적과정에서 가장 큰 길이인 4를 알 수 없으므로 끝에서부터 역추적하는 과정이 훨씬 단순.

 

소스코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#define FASTio ios_base :: sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define endl '\n' 

using namespace std;

int n;

vector<int> v(1001,0);
int d[1001];
int ans;

stack<int> st;
int main()
{
    FASTio;
    cin >> n;

    for(int i=0;i<n;i++)
    {
        cin >> v[i];
        d[i] = 1;
    }

    for(int i=0;i<n;i++)
    {  
        for(int j=i+1;j<n;j++)
        {
            if(v[j] > v[i])
            {   
                d[j] = max(d[i] + 1, d[j]);
            }
        }
    }

    for(int i=0;i<n;i++)
    {   
        ans = max(ans, d[i]);
    }

    cout << ans << endl;

    int k = 1;

    for(int i=0;i<n;i++)
    {
        if(d[i]==k)
        {
            st.push(v[i]);
            k++;
        }
    }
    while(!st.empty())
    {
        cout << st.top() << ' ';
        st.pop();

    }
    return 0;
}