* 공부 목표
DP - 1463, 11726, 11727, 9095, 10844, 11057, 2193, 9465, 2156, 11053, 11055, 11722, 11054, 1912, 2579, 1699, 2133, 9461, 2225, 2011, 11052
문) 수열 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의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.
풀이
1. 처음 생각해서 망한 풀이
- k = Max 값 || SecondMax값
- k값 이전까지는 증가 부분 수열, k값 이후에는 감소 부분 수열
- k가 Max일 때와 SecondMax일 때 중 더 긴 쪽이 정답
예제에 나온 답 제외하고 다른 반례는 맞게 출력됐다.
어떤 부분이 문제였나?
수열 내 Max값이 2개 이상 있을 때 기준이 되는 k가 먼저 나온 값이 됨.
따라서 바이토닉 수열은 맞지만 <가장 긴 수열>은 아니므로 정답이 아니게 됨.
(사실 이게 아니더라도 너무 길고 재사용성 낮은 코드라 런타임 에러 떴을 확률이 높았음.)
2. 다른 풀이의 아이디어
- 오름차순 부분 수열, 내림차순 부분 수열을 각각 구한다.
- 두 개의 부분 수열을 합한다.
- 누적된 값(dp[i]) 중 최댓값을 구한다. ➡️ 결과
- 원소가 1개씩 중복되어 있으므로 결과에서 -1을 해줘야 정답
코드
import java.util.*;
import java.io.*;
public class Main {
static int n;
static int[] arr;
static int[] first;
static int[] after;
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
arr = new int[n];
first = new int[n];
after = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
for(int i=0; i<n; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
first();
after();
//max 값 찾기
int max = 0;
for(int i=0; i<n; i++) {
max = (max < first[i] + after[i]) ? first[i] + after[i] : max;
} System.out.println(max - 1);
br.close();
}
public static void first() {
for(int i=0; i<n; i++) {
first[i] = 1;
for(int j=0; j<i; j++) {
if(arr[j] < arr[i] && first[i] < first[j] +1) first[i] = first[j] + 1;
}
}
}
public static void after() {
//시작이 뒤
for(int i=n-1; i >= 0; i--) {
after[i] = 1;
for(int j=n-1; j>=0; j--) {
if(arr[j] < arr[i] && after[i] < after[j] +1) after[i] = after[j] + 1;
}
}
}
}
각 수열을 따로 구해 더한다는 개념은 생각하지 못해서 충격이었다.🥹
머리 쥐어 싸매며 고민해도, 구상이 잘못되면 처음부터 새로 해야한다.
열심히... 더 많이... 배워야겠다.
'알고리즘' 카테고리의 다른 글
[백준] DP - 1912번, 연속합 (0) | 2023.10.25 |
---|---|
[백준] 문자열 처리 - 10820번, 문자열 분석 (0) | 2023.10.24 |
[백준] 큐 - 18258번 (1) | 2023.10.18 |
[백준] DP - 11722번, 가장 긴 감소하는 부분 수열 (0) | 2023.10.18 |
[백준] 스택 - 9012번 괄호 | 1개만 입력 받기, stack 처리 (1) | 2023.10.06 |