11054번: 가장 긴 바이토닉 부분 수열
첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)
www.acmicpc.net
얼핏 보기엔 복잡하고 어려워보이는 문제였지만, LIS와 LDS를 구하는 dp함수를 구현하면 간단히 풀 수 있는 문제였다.
중심점 here을 기준으로 arr[1] ~ arr[here] 까지 LIS + arr[here] ~ arr[N] 까지 LDS - 1 이 바이토닉 부분 수열의 길이가 되고, 중심점 here을 1~N으로 했을 때 가장 큰 값이 문제의 정답이 된다.
#include <iostream>
using namespace std;
int N, arr[1001], LIS[1001], LDS[1001];
int max(int a, int b) { return a > b ? a : b; }
int Topdown_LIS(int here)
{
int& ret = LIS[here];
if (ret != 0) return ret;
ret = 1;
for (int i = 1; i < here; i++)
if (arr[i] < arr[here])
ret = max(ret, Topdown_LIS(i) + 1);
return ret;
}
int Topdown_LDS(int here)
{
int& ret = LDS[here];
if (ret != 0) return ret;
ret = 1;
for (int i = here + 1; i <= N; i++)
if (arr[i] < arr[here])
ret = max(ret, Topdown_LDS(i) + 1);
return ret;
}
int Bottomup_LIS(int here)
{
for (int i = 1; i <= here; i++)
{
LIS[i] = 1;
for (int j = 1; j < i; j++)
if (arr[i] > arr[j])
LIS[i] = max(LIS[i], LIS[j] + 1);
}
return LIS[here];
}
int Bottomup_LDS(int here)
{
for (int i = N; i >= here; i--)
{
LDS[i] = 1;
for (int j = i + 1; j <= N; j++)
if (arr[i] > arr[j])
LDS[i] = max(LDS[i], LDS[j] + 1);
}
return LDS[here];
}
int main(void)
{
cin >> N;
for (int i = 1; i <= N; i++)
cin >> arr[i];
// top-down
int res = 1;
for (int i = 1; i <= N; i++)
res = max(res, Topdown_LIS(i) + Topdown_LDS(i) - 1);
cout << res << endl;
// bottom-up
res = 1;
for (int i = 1; i <= N; i++)
res = max(res, Bottomup_LIS(i) + Bottomup_LDS(i) - 1);
cout << res << endl;
return 0;
}
알고리즘 200일 프로젝트 - 88 day
'알고리즘 > BOJ' 카테고리의 다른 글
백준 2225번: 합분해 (0) | 2020.07.03 |
---|---|
백준 1520번: 내리막 길 (0) | 2020.07.03 |
백준 11722번: 가장 긴 감소하는 부분수열 (0) | 2020.07.02 |
백준 1904번: 01타일 (0) | 2020.07.01 |
백준 11051번: 이항 계수 2 (0) | 2020.06.30 |