티스토리 뷰

algorithm/problem solving

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

무니웜테일패드풋프롱스 2020. 4. 17. 14:13

 

 

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

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

www.acmicpc.net

이 문제를 풀기전에 먼저 '가장 긴 증가하는 부분 수열' 문제를 풀기를 권장한다! 왜냐하면 해당 문제를 응용해서 푸는 문제이기 때문이다. 

 

S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN

이렇게 생긴 수열을 바이토닉 수열이라고 한다. 

여기서 보이는 규칙은 Sk 값을 기준으로 왼쪽은 '증가하는 부분 수열' 이고 오른쪽은 '감소하는 부분 수열' 이라는 점이다.

그렇다! Sk 값의 가장 긴 바이토닉 부분 수열은 결국

0부터 Sk까지의  가장 긴 증가하는 부분 수열 + Sk부터 Sn까지의 가장 긴 감소하는 부분 수열 -1 이다 

(여기서 -1은 Sk값이 두번 겹치기 때문에 해줘야한다.)

 

그러면 일단 배열을 세개 만들어준다. 첫번째는 각 Si 값들의 가장 긴 증가하는 부분 수열 길이 저장

두번째는 각 Si 값들의 가장 긴 감소하는 부분 수열 길이 저장,

그리고 세번째는 이 두개를 합친 각 Si 값들의 가장 긴 바이토닉 부분 수열 길이를 저장해준다.

 

그러면 첫번째로 0부터 k 값까지의 가장 긴 증가하는 부분 수열을 구해주는 소스를 보자 (여기서 k는 0부터 n-1까지이다)

for(int i=0; i<n; i++) {
	inc[i]=1;
	for(int j = 0; j<i;j++) {
		if(arr[i]>arr[j] && inc[j]+1>inc[i]) inc[i]=inc[j]+1;
	}
}

소스를 통해 알 수 있듯 왼쪽 - 오른쪽의 가장 긴 증가하는 부분 수열값을 inc 배열에 저장해주고 있다. 

 

두번째로 k 값부터 n 까지의 가장 긴 감소하는 부분 수열을 구해주는 소스이다.(여기서 k는 n-1부터 0까지이다)

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

 

그리고 이 두 루프를 한 루프로 합친 소스이다. (but 루프를 두개로 나누어도 상관없다. 시간복잡도는 어차피 O(n^2)으로 같기 때문이다.

for(int i=0; i<n; i++) {
	inc[i]=1;
	dec[n-i-1]=1;
	for(int j = 0; j<i;j++) {
		if(arr[i]>arr[j] && inc[j]+1>inc[i]) inc[i]=inc[j]+1;
		if(arr[n-i-1]>arr[n-j-1]&& dec[n-j-1]+1>dec[n-i-1]) dec[n-i-1]=dec[n-j-1]+1;
	}
}

 

 

그러면 아래는 전체 자바 소스이다.

import java.util.*;
import java.io.*;

public class Main {	
	private static int [] arr;
	private static int[]dec;
	private static int[]inc;
	private static int[]res;
	public static void main(String[] args)throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer stk= new StringTokenizer(br.readLine());
		int n = Integer.parseInt(stk.nextToken()); //수열 길이 
		arr = new int[n];
		dec = new int[n]; //감소 
		inc = new int[n]; //증가
		res = new int[n];
		String[] s;
		s = br.readLine().split(" ");
		for(int i=0; i< n;i++) {
			arr[i]=Integer.parseInt(s[i]);
		}
		for(int i=0; i<n; i++) {
			inc[i]=1;
			dec[n-i-1]=1;
			for(int j = 0; j<i;j++) {
				if(arr[i]>arr[j] && inc[j]+1>inc[i]) inc[i]=inc[j]+1;
				if(arr[n-i-1]>arr[n-j-1]&& dec[n-j-1]+1>dec[n-i-1]) dec[n-i-1]=dec[n-j-1]+1;
			}
		}
		int max=0;
		for(int i=0; i<n; i++) {
			res[i]=inc[i]+dec[i]-1;
			if(max<res[i]) max=res[i];
		}
		System.out.println(max);
		
	}
}

'algorithm > problem solving' 카테고리의 다른 글

BOJ 15686 치킨배달  (0) 2020.05.03
BOJ 2565 전깃줄  (0) 2020.04.17
BOJ 2579 계단 오르기  (0) 2020.04.15
BOJ 2156 포도주 시식  (0) 2020.04.14
BOJ 1931 회의실배정  (0) 2020.04.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함