#문제

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

예를 들어, {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 ≤ Ai ≤ 1,000)

출력

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

 

#작성 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <cstdio>
using namespace std;
 
int N;
int A[1001];    // 인덱스 1~1000 사용
int up[1001], down[1001];
 
int solve(){
    // up, down 배열을 1로 초기화한다. 
    fill_n(up, 10011);
    fill_n(down, 10011);
    
    // A[i]까지 증가하는 부분수열 구한다. 
    for(int i=1; i<=N; i++){
        for(int j=1; j<=i; j++){
            if( A[j] < A[i] ){
                up[i] = max(up[i], up[j]+1);
            }
        }
    }
    
    // 뒤에서부터 A[i]까지 증가하는 부분수열 구한다.
    //  == A[i]에서 끝까지 감소하는 부분수열 구한다. 
    for(int i=N; i>=1; i--){
        for(int k=N; k>=i; k--){
            if( A[i] > A[k] ){
                down[i] = max(down[i], down[k]+1);
            }
        }
    }
    int result=0;
    for(int i=1; i<=N; i++){
        result = max(result, up[i]+down[i]-1);
        // up[i]와 down[i]에 A[i]가 중복포함되므로 하나 제거해야한다 
    }
    return result;
}
int main(){
    // 입력 
    scanf("%d"&N);
    for(int i=1; i<=N; i++){
        scanf("%d"&A[i]);
    }
    
    // 출력 
    printf("%d\n",solve());
    return 0;
cs

#191206 REVIEW

더보기
/* 11054 가장 긴 바이토닉 부분수열 */
#DP

int N;
int A[1001];              // 인덱스 1~1000을 사용한다. 수열을 저장할 배열.
int up[1001], down[1001];    // i번째에 A[i]까지 증가하는/감수하는 부분수열 원소 개수를 저장할 것. 

int solve(){
	up[1001]배열, down[1001]배열을 모두 1로 초기화한다.
	
	앞에서부터 A[i]까지 증가하는 부분수열을 구한다.
	for(int i=1; i<=N; i++){
		for(int j=1; j<i; j++){
			if( A[j] < A[i] ){
				up[i] = max(up[i], up[j]+1);
			}
		}
	}
	
	뒤에서부터 A[i]까지 증가하는 부분수열을 구한다.
	== A[i]부터 맨 뒤까지 감소하는 부분수열을 구한다.
	for(int i=N; i>=1; i--){
		for(int j=N; j>i; j--){
			if( A[i] > A[j] ){
				down[i] = max(down[i], down[j]+1);
			}
		}
	}
	
	up[i] + down[i]의 합이 가장 큰 것을 구하고, 1을 뺀 후에 return 해준다.
	1을 빼는 이유는 up[i]와 down[i] 모두에 A[i]가 포함되기때문에 두 번 포함되는 것 중 하나를 빼주는 것.
}

 

'BOJ' 카테고리의 다른 글

BOJ 2565번 :: 전깃줄  (0) 2019.12.07
BOJ 9012번 :: 괄호  (0) 2019.12.06
BOJ 7569번 :: 토마토 (2)  (0) 2019.12.06
BOJ 7576번 :: 토마토  (0) 2019.12.06
BOJ 2178번 :: 미로 탐색  (0) 2019.12.06

+ Recent posts