자료구조, 알고리즘/문제풀이
[알고리즘] 가장 긴 바이토닉 부분 수열 - 백준 11054
wnstjd
2024. 6. 4. 23:13
문제
가장 긴 증가하는 부분 수열의 응용 문제이다.
풀이
가장 긴 증가하는 부분 수열의 풀이 방법을 이용한다.
1. 배열의 시작점부터 가장 긴 증가하는 부분 수열의 풀이 방법을 이용하여 0 ~ idx까지의 증가하는 부분 수열의 길이를 구한다.
2. 배열의 끝지점부터 가장 긴 증가하는 부분 수열의 풀이 방법을 이용하여 (배열의 크기 + 1) ~ idx까지 역순으로 증가하는 부분 수열의 길이를 구한다.
3. 구한 두 수열의 개수를 더하여 각 idx의 바이토닉 부분 수열의 길이를 구한다.
4. 가장 긴 바이토닉 부분 수열의 길이를 구한다.
표로 나타내면 아래처럼 된다.
idx | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
arr | 0 | 1 | 5 | 2 | 1 | 4 | 3 | 4 | 5 | 2 | 1 | 0 |
right -> | 0 | 1 | 2 | 2 | 1 | 3 | 3 | 4 | 5 | 2 | 1 | 0 |
left <- | 0 | 1 | 5 | 2 | 1 | 4 | 3 | 3 | 3 | 2 | 1 | 0 |
dp | 0 | 1 | 6 | 3 | 1 | 6 | 5 | 6 | 7 | 3 | 1 | 0 |
코드
#include<iostream>
using namespace std;
int arr[1002], rightDP[1002], leftDP[1002], DP[1002], n;
int solution()
{
int rightMax = 0, leftMax = 0, maxDP = 0;
for (int i = 1; i <= n; i++)
{
rightMax = 0;
leftMax = 0;
for (int j = 0; j < i; j++)
{
// 1. 오른쪽 방향 수열
if(arr[j] < arr[i])
rightMax = max(rightMax, rightDP[j]);
// 2. 왼쪽 방향 수열
if (arr[n + 1 - j] < arr[n + 1 - i])
leftMax = max(leftMax, leftDP[n + 1 - j]);
}
rightDP[i] = rightMax + 1;
leftDP[n + 1 - i] = leftMax + 1;
}
for (int i = 1; i <= n; i++)
{
// 3. 바이토닉 수열 길이 구하기
DP[i] = rightDP[i] + leftDP[i] - 1;
// 4. 가장 긴바이토닉 수열 길이 구하기
maxDP = max(maxDP, DP[i]);
}
return maxDP;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> arr[i];
cout << solution();
}