Algorithm

[BOJ] 가장 긴 증가하는 부분 수열 4 14002번 C++

따봉치치 2024. 2. 23. 16:00
728x90

 

 

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {1020, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

 

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

둘째 줄에는 가장 긴 증가하는 부분 수열을 출력한다. 그러한 수열이 여러가지인 경우 아무거나 출력한다.

 

접근 방식

 

가장 유명한 DP 문제인 가장 긴 증가하는 부분 수열의 변형 문제이다

수열의 길이 자체는 DP로 간단하게 풀 수 있다

for 반복문을 i를 1 ~ N번 돌면서

이중 반복문으로 j를 i-1 ~ 1 을 확인하면서

arr[i]가 arr[j]보다 클 시 dp[i]를 dp[i], dp[j]+1 중에 큰 값으로 정해주면 된다.

이때, 부분 수열 자체를 구하는 것은

이미 정해둔 dp값중에 가장 큰 값을 가져와서

큰값부터 해당하는 인덱스를 배열에서 가져오면 된다!

 

처음에는 dp 돌면서 부분 수열을 같이 구해주려고 했는데 

그렇게 하니까 모든 배열이 담겼다 ;;

 

코드

#include<bits/stdc++.h>
using namespace std;

int N;
int arr[1002], dp[1001];
vector<int> ans;

int main() {
    cin>>N;
    for(int i=1; i<=N; i++) cin>>arr[i];

    for(int i=1; i<=N; i++) {
        dp[i] = 1;
        for(int j=i-1; j>=1; j--) {
            if(arr[i] > arr[j]) {
                dp[i] = max(dp[i], dp[j]+1);
            }
        }
    }

    int max_len = *max_element(dp+1, dp+N+1);
    cout<<max_len<<'\n';
    
    for(int i=N; i>=1; i--) {
        if(dp[i] == max_len) {
            ans.push_back(arr[i]);
            max_len--;
        } 

    }

    for(int i=ans.size()-1; i>=0; i--) cout<<ans[i]<<" ";
}
728x90