[백준] 11054번 가장 긴 바이토닉 부분 수열 - Python / 알고리즘 기초 1/2 - 다이나믹 프로그래밍 1 (연습)

ByungJik_Oh·2025년 4월 2일
0

[Baekjoon Online Judge]

목록 보기
64/244
post-thumbnail



💡 문제

수열 S가 어떤 수 Sk_k를 기준으로 S1_1 < S2_2 < ... Sk1_{k-1} < Sk_k > Sk+1_{k+1} > ... SN1_{N-1} > SN_N을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.

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

출력

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


💭 접근

문제가 좀 복잡할 수도 있는데, 쉽게 말해 각 자리의 원소보다 오른쪽에 있는 수는 증가하는 부분 수열의 형태를 띄고, 왼쪽에 있는 수는 감소하는 부분 수열의 형태를 띄는 수열을 구해야한다. 문제의 예시를 보면 {10, 20, 30, 25, 20} 과 같이 30을 기준으로 오른쪽은 증가하는 수열, 왼쪽은 감소하는 수열의 형태를 보인다.

11053번 가장 긴 증가하는 부분 수열 문제와 11722번 가장 긴 감소하는 부분 수열 문제를 섞은 형태의 문제라고 할 수 있다. 이를 활용하여 각 원소마다 증가/감소하는 부분 수열의 길이를 따로 구한 뒤 더하면 정답을 구할 수 있다.

  1. 우선 입력받은 a와 이를 반전시킨 reversed_a를 만든다.

  2. 증가하는 부분 수열 길이를 저장할 dp_inc와 감소하는 부분 수열 길이를 저장할 dp_dec를 선언한다.

  3. 각 dp에 대해 수열 길이를 저장한다.

  4. dp_dec의 경우 뒤집어진 입력으로 길이를 저장하였기 때문에 dp_inc와 더해주기 위해 반전시켜준다.

  5. 더한 값의 최대값을 출력한다.

따라서 점화식은 다음과 같이 도출할 수 있다.

if a[i] > a[j]:
	dp_inc[i] = max(dp_inc[i], dp_inc[j] + 1)
if reversed_a[i] > reversed_a[j]:
	dp_dec[i] = max(dp_dec[i], dp_dec[j] + 1)

📒 코드

n = int(input())
a = list(map(int, input().split()))
reversed_a = a[::-1]
dp_inc = [1 for _ in range(n)] # 증가하는 수열
dp_dec = [1 for _ in range(n)] # 감소하는 수열

for i in range(1, n):
    for j in range(i):
        if a[i] > a[j]:
            dp_inc[i] = max(dp_inc[i], dp_inc[j] + 1)
        if reversed_a[i] > reversed_a[j]:
            dp_dec[i] = max(dp_dec[i], dp_dec[j] + 1)

dp_dec = dp_dec[::-1] # 감소하는 수열 다시 반전

# 각 dp가 1로 시작했기 때문에 중복값을 빼주기 위해 -1
ans = [dp_inc[i] + dp_dec[i] - 1 for i in range(n)]
print(max(ans))

💭 후기

11053번 가장 긴 증가하는 부분 수열 문제와 11722번 가장 긴 감소하는 부분 수열 문제를 먼저 풀어보았다면 어렵지 않게 해결할 수 있는 문제.


🔗 문제 출처

https://www.acmicpc.net/problem/11054


profile
精進 "정성을 기울여 노력하고 매진한다"

0개의 댓글