https://www.acmicpc.net/problem/11054
🌘 문제 이해하기
- 수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.
- 수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.
- 첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)
- 첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.
🌗 문제 자세히보기
바이토닉 수열이랑 어느 하나 기준점을 잡고 왼쪽은 증가하는 수열 , 오른쪽은 감소하는 수열이다.
ex)
- 바이토닉 수열 : {1 , 3 , 4 , 5 , 2 , 1}
- 증가하는 수열만 있어도 바이토닉 수열 : {10, 20, 30, 40}
- 감소하는 수열만 있어도 바이토닉 수열 : {50, 40, 25, 10}
- 증가했다 감소했다 증가했다 감소하는것 안된다 ❌
바이토닉 수열은 어느 하나 기준점을 잡으면 된다.
기준점을 임의로 잡고 기준점을 기준으로 왼쪽의 증가 부분 수열 길이 , 오른쪽의 감소 부분 수열 길이 를 더하여 가장 긴 바이토닉 수열의 길이 인 것을 찾는다.
즉 증가하는 부분 수열과 감소하는 부분수열의 동시에 구하면 된다.
# 바이토닉 수열 푸는 방법
1. 증가하는 부분 수열 구하기
- 증가하는 부분 수열은 0 부터 임의의 기준점의 위치 까지 증가 부분 수열의 최대 길이를 찾는다.
(배열은 0부터 시작하니 시작은 0) - 증가하는 부분 수열은 기준 값 과 비교값을 설정하여 최장 부분 수열의 크기를 저장한다.
for(int i=0;i<n;i++) //임의의 기준 값
{
for(int j=0;j<i;j++) //비교값
{
if(arr[i] > arr[j])
{
dp1[i] = Math.max(dp1[i], dp1[j]+1);
}
}
}
2. 감소하는 부분 수열 구하기
- 감소하는 부분 수열은 임의의 기준점 부터 마지막 n-1 위치까지 감소 부분 수열의 최대 길이를 찾는다.
- 감소하는 부분 수열은 증가하는 부분 수열의 범위와 반대 이므로 역순으로 계산한다.
- 기준 값과 비교값을 설정하여 최장 부분 수열의 크기를 저장한다.
for(int i=n-1;i>=0;i--)
{
for(int j=n-1;j>i;j--)
{
if(arr[i]>arr[j])
{
dp2[i] = Math.max(dp2[i], dp2[j]+1);
}
}
}
3. 증가,감소 부분 수열의 최대 길이들을 저장한 dp1 , dp2 를 더해 최종 바이토닉 수열의 길이를 저장한다.
4. 이 중 가장 긴 바이토닉 수열의 길이를 출력한다.
import java.io.*;
import java.util.*;
public class Main{
public static void main(String[] args) throws IOException
{
//기준값 을 구해서 왼쪽으로는 증가 수열 , 오른쪽으로는 감소 수열 중 최대 길이를 구하여라
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int[] arr = new int[n+1];
int[] dp1 = new int[n+1]; //증가수열
int[] dp2 = new int[n+1]; //감소수열
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i=0;i<n;i++)
{
arr[i] = Integer.parseInt(st.nextToken());
dp1[i] = 1;
dp2[i] = 1;
}
int result = Integer.MIN_VALUE;
//증가수열
for(int i=0;i<n;i++) //기준값
{
for(int j=0;j<i;j++) //비교값
{
if(arr[i] > arr[j])
{
dp1[i] = Math.max(dp1[i], dp1[j]+1);
}
}
}
//감소수열
for(int i=n-1; i>=0;i--) //기준값
{
for(int j=n-1;j>i;j--) //비교값
{
if(arr[i]>arr[j])
{
dp2[i] = Math.max(dp2[i], dp2[j]+1);
}
}
}
for(int i=0;i<n;i++)
{
result = Math.max(result, dp1[i] + dp2[i] -1);
}
System.out.println(result);
}
}
'항해' 카테고리의 다른 글
[Day34]JAVA 프로그래머스 개인정보 수집 유효기간 (1) | 2024.12.01 |
---|---|
[Day33]JAVA 프로그래머스 신규 아이디 추천 (1) | 2024.11.29 |
[Day31]JAVA 백준 줄세우기(2631번) (0) | 2024.11.27 |
[Day30]JAVA 백준 상자 넣기(1965번) (0) | 2024.11.26 |
[Day29]JAVA 백준 파도 수열(9461번) (0) | 2024.11.25 |