본문 바로가기

백준/골드

[백준 11054번] 가장 긴 바이토닉 부분 수열 (C++)

문제링크 : https://www.acmicpc.net/problem/11054

 

11054번: 가장 긴 바이토닉 부분 수열

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

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 987654321;

int arr[1001];
int dp_plus[1001];
int dp_minus[1001];

int main()
{
    ios_base::sync_with_stdio(0); 
	cin.tie(0);
    
    int N;
    cin >> N;

    for(int i=0; i<N; i++)
    {
        cin >> arr[i];
        dp_plus[i]=1; //최소길이 1
        for(int j=0; j<i; j++)
        { 
            if(arr[i]>arr[j]) dp_plus[i] = max(dp_plus[i], dp_plus[j]+1); //가장 긴 증가하는 수열 저장
        }
    }

    for(int i=N-1; i>=0; i--)
    {
        dp_minus[i]=1; //최소길이 1
        for(int j=N-1; j>i; j--)
        {
            if(arr[i]>arr[j]) dp_minus[i] = max(dp_minus[i], dp_minus[j]+1); //가장 긴 감소하는 수열 저장
        }
    }

    int result = 0;
    for(int i=0; i<N; i++)
    {
        result = max(result, dp_plus[i] + dp_minus[i]); //가장 긴 바이토닉 수열 저장
    }
    cout << result-1; //중복된 부분 빼주기

    return 0;
}

가장 긴 증가하는 수열과 가장 긴 감소하는 수열을 각각 따로 구해준다.

바이토닉 수열은 증가했다가 다시 감소하는 형태이므로 위에서 구한 각 수열들을 더해주면 된다.

이때 증가의 마지막이자 감소의 시작이 되는 부분은 중복이되기에 -1을 해주면된다.

 

증가하는 수열은 현재값과 그전값들을 비교하며 그전값보다 큰 경우 1을 더해준다.

감소하는 수열은 시작점을 역순으로하여 현재값과 그전값들을 비교하여 그전값보다 큰 경우 1을 더해준다.

(입력받은 수열의 맨 뒤에서부터 증가하는 수열을 찾는 것)

 

이때 주의해야할 것은 기본적으로 수열의 길이가 최소 1이라는 것이다. (자기 자신)

따라서 초기화를 1로 시작하고 해야한다.

<예제>
1 5 2 1 4 3 4 5 2 1

증가하는 수열 (길이 5)
1 x 2 x x 3 4 5 x x

감소하는 수열 (길이 3)
x x x x x x x 5 2 1

중복되는 값 5

5 + 3 - 1 = 7

'백준 > 골드' 카테고리의 다른 글

[백준 11401번] 이항 계수 3 (C++)  (0) 2023.08.17
[백준 13172번] Σ (C++)  (0) 2023.08.16
[백준 14502번] 연구소 (C++)  (0) 2023.08.14
[백준 15686번] 치킨 배달 (C++)  (0) 2023.08.12
[백준 10830번] 행렬 제곱 (C++)  (0) 2023.08.11