공부/백준

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

상연 2020. 11. 25. 11:45

목차

    www.acmicpc.net/problem/11054

     

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

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

    www.acmicpc.net

    코드

    #include <iostream>
    using namespace std;
    
    int n;
    int A[1000];
    int inc_arr[1000];
    int dec_arr[1000];
    int len = 0;
    int max(int a, int b){
    	return a > b ? a : b;
    }
    
    void init(){
    	cin >> n;
    	for(int i=0; i<n; i++){
    		cin >> A[i];
    	}
    }
    
    void solve(){
    	for(int i=0; i<n; i++){
    		inc_arr[i] = 1;
    		dec_arr[i] = 1;
    		for(int j=0; j<i; j++){
    			if(A[i] > A[j]){
    				inc_arr[i] = max(inc_arr[i], inc_arr[j] + 1);
    			}
    			if(A[i] < A[j]){
    				dec_arr[i] = max(inc_arr[j] + 1, dec_arr[i]);
    				dec_arr[i] = max(dec_arr[i], dec_arr[j] + 1);
    			}
    		}
    		len = max(inc_arr[i], len);
    		len = max(dec_arr[i], len);
    	}
    	cout << len;
    }
    int main() {
    	init();
    	solve();
    	return 0;
    }

    문제

    지문 자체가 난해한 문제는 아닙니다. 문제 그대로

    수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면,

    그 수열을 바이토닉 수열이라고 한다.

    이 바이토닉 수열을 찾으면 되는 문제죠.

     

    풀이

    단순히 계속 증가해서 커지는 수열만 찾는것도, 계속 감소해서 작아지는 수열만 찾는것도 아닙니다.

    두 개 다 찾아야 하죠. 계속 증가하다가 계속 감소하는 수열을 찾아야 하기 때문에 

    각 각의 수열의 길이를 저장할 배열을 두 개 선언하겠습니다.

    int n; // 수열을 이루는 수의 개수 n
    int A[1000]; // 수열 A
    int inc_arr[1000]; // 증가하는 수열
    int dec_arr[1000]; // 감소하는 수열
    int len = 0; // 최장길이

    따라서 변수의 선언은 위와 같습니다.

    그럼 이것을 활용해서 어떻게 풀 수 있을까요?

    다른 블로그 글 같은걸 보니, 대부분은 이제

    (왼쪽에서 오른쪽으로 증가하는 수열길이) + (오른쪽에서 왼쪽으로 증가하는 수열 길이) - 1

    이렇게 해서 풀이를 하셨습니다. 근데 저 같은 경우에는 조금 다르게 풀었는데요.

    우선, 정답이 될 수 있는 경우의 수에 대해 잠깐 짚고 넘어가겠습니다.

    • 계속해서 증가하는 수열이 가장 긴 경우
    • 계속해서 감소하는 수열이 가장 긴 경우
    • 증가하다 감소하는 수열이 가장 긴 경우

    해서 점화식도 세 개 정도로 생각하면 될 것 같습니다.

    1. 계속 증가하는 수열

    이 문제는 

    wonsang98.tistory.com/77

     

    백준 11053번: 가장 긴 증가하는 부분 수열(C++)

    www.acmicpc.net/problem/11053 11053번: 가장 긴 증가하는 부분 수열 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인..

    wonsang98.tistory.com

    제가 여기서 풀이를 작성해 놨습니다. 이 풀이랑 똑같이해서 증가하는 수열의 개수를 알아냅니다.

    inc_arr[i] = max(inc_arr[i], inc_arr[j] + 1)

    2. 계속해서 감소하는 수열

    이는 1번의 반대로 해주면됩니다.

    1번의 조건이 A[i] > A[j] 였다면, 2번의 경우는 작아져야하니 A[i] < A[j]가 되겠죠.

    dec_arr[i] = max(dec_arr[i], dec_arr[j] + 1)

    3. 증가하다 감소하는 수열

    A[i] < A[j] 인 경우, 즉 감소하는 조건일 때

    이전까지 증가하고 있던 수열 inc_arr[j] + 1 값입니다.

    dec_arr[i] = max(dec_arr[i], inc_arr[j] + 1)

     

    위의 세 개의 점화식의 계산 값 중 가장 큰 값이 정답이 됩니다.

    또한, 틀렸는데 어디서 틀렸는지 모르시는 분들은 

    www.acmicpc.net/board/view/56223

     

    글 읽기 - 가장 긴 바이토닉 수열 반례 및 필독FAQ 모음

    댓글을 작성하려면 로그인해야 합니다.

    www.acmicpc.net

    여기서 반례를 한 번 찾아보시길 추천드립니다.