알고리즘 문제풀이

[BOJ] 11054번 - 가장 긴 바이토닉 부분 수열 본문

자료구조 + 알고리즘/[BOJ]

[BOJ] 11054번 - 가장 긴 바이토닉 부분 수열

JoonDev 2020. 11. 13. 00:10

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

시간제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 17643 9222 7349 52.530%

문제

수열 S가 어떤 수 ${S_k}$를 기준으로 ${S_1< S_2< ... S_{k-1}< S_k> S_{k+1}> ... S_{N-1}> S_N}$을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.

예를 들어, {10, 20,30, 25, 20}과 {10, 20, 30,40}, {50, 40, 25, 10} 은 바이토닉 수열이지만, {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.

수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.

입력

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

출력

첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.

예제 입력 1

10
1 5 2 1 4 3 4 5 2 1

예제 출력 1

7

힌트

예제의 경우 {1 5 2 1 4 3 4 5 2 1}이 가장 긴 바이토닉 부분 수열이다.

출처

https://www.acmicpc.net/problem/11054

알고리즘 분류

  • LIS
  • LDS
  • DP

접근 방법

가장 긴 바이토닉 수열을 구하기 위해, ${{A_1, A_2, ... , A_n}}$ 사이의 원소 $A_k$ 을 마지막 원소로 가지는 Longest Increasing Sequences 의 길이와 $A_k$ 를 첫번째 원소로 가지는 Longest Decreasing Sequences 의 합으로 표현되는 bitonic 수열의 가장 긴 길이를 따로 저장하여 그 중 최댓값을 출력하면 그것이 문제에서 찾고자 한 가장 긴 바이토닉 수열의 길이이다.

${lis[i]}$ 를 i번째 원소를 마지막으로 가지는 최장증가부분수열의 길이라고 정의하자.
${lds[i]}$ 를 i번째 원소를 첫번째로 가지는 최장감소부분수열의 길이라고 정의하자.
${lis[i] + lds[i]}$ 의 길이는 i번째원소를 2번 포함한 길이를 의미하므로 그것에서 -1 을 해준것이 바이토닉 수열의 길이이다.

소스 코드

#include <iostream>
#include <vector>

using namespace std;

int main(void){
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int N;
    cin >> N;
    vector<int> arr(N);
    for(int i=0; i<N; i++){
        cin >> arr[i];
    }

    vector<int> lis(N), lds(N);
    vector<int> bitonic(N);

    for(int i=0; i<N; i++){
        lis[i] = 1;
        for(int j=0; j<i; j++){
            if( arr[j] < arr[i] && lis[j]+1 > lis[i] ){
                lis[i] = lis[j]+1;
            }
        }
    }
    for(int i=N-1; i>=0; i--){
        lds[i] = 1;
        for(int j= i+1; j < N ; j++){
            if( arr[i] > arr[j] && lds[i] < lds[j]+1 ){
                lds[i] = lds[j] + 1;
            }
        }
    }

    for(int i=0; i<N; i++){
        // 자기 자신이 중복됨. (-1)
        bitonic[i] = lis[i] + lds[i] - 1;

    }

    int max_len  = -1;
    for(auto it : bitonic){
        if( max_len < it )
            max_len = it;
    }
    cout << max_len;

    return 0;
}

'자료구조 + 알고리즘 > [BOJ]' 카테고리의 다른 글

[BOJ] 2110번 - 공유기 설치  (0) 2020.11.14
[BOJ] 1245번 - 농장 관리  (0) 2020.11.13
[BOJ] 11055번 - 가장 큰 증가 부분 수열  (0) 2020.11.12
[BOJ] 2631번 - 줄 세우기  (0) 2020.11.12
[BOJ] 3190번 - 뱀  (0) 2020.11.12
Comments