https://www.acmicpc.net/problem/11054
[필자 사고]
동적 프로그래밍 문제이다.
언뜻 봤을 때는 LIS문제 같아 보이지만
LIS문제를 응용한 문제이다.
dp배열을 2개 만들어 시작부분과 끝부분에서 각 시작하여
각 인덱스마다 2개의 배열을 더한 값-1 이 가장 큰값을 출력해야 된다.
필자는 해당 LIS를 구할 때 초기값을 1 로 설정을 안해서 출력값이 계속 1보다 작은 문제가 발생했었다.
이 부분 주의해야 겠다.
개인적으로 해당 문제에서 LIS지식을 2개를 이용하여 처음 부분과 끝부분으로 알고리즘 적용한게 인상적이였다.
[코드 해설]
- 입력 처리 (Input 함수)
Input() 함수는 배열의 크기 N을 입력받고, 이를 기반으로 배열 arr, dp, rDp를 초기화한다.
- arr 배열은 입력받은 수열을 저장하며, dp와 rDp는 각각 정방향과 역방향에서의 최장 증가 부분 수열(LIS, Longest Increasing Subsequence) 길이를 저장하는 벡터이다.
- arr2는 arr을 뒤집은 배열로, reverse(arr2.begin()+1, arr2.end())을 사용하여 첫 번째 원소를 제외한 나머지를 뒤집는다. 이를 통해 역방향에서의 LIS를 계산할 수 있도록 한다.
- 최장 바이토닉 수열 계산 (Game_Start 함수)
Game_Start() 함수는 dp와 rDp를 활용하여 최장 바이토닉 부분 수열(Longest Bitonic Subsequence)을 계산한다.
- dp[i]는 i번째 원소를 끝으로 하는 최장 증가 부분 수열의 길이를 나타낸다.
- rDp[i]는 arr2를 이용하여 i번째 원소를 시작으로 하는 최장 증가 부분 수열의 길이를 계산한 후, 다시 뒤집어 원래 배열의 역방향 LIS 값을 저장한다.
- 두 개의 LIS 정보를 조합하여 최장 바이토닉 부분 수열의 길이를 구한다.
이 과정에서 이중 루프를 사용하여 dp와 rDp를 채운다.
- dp[i] = max(dp[i], dp[k] + 1), rDp[i] = max(rDp[i], rDp[k] + 1)을 이용하여 LIS 값을 갱신한다.
- reverse(rDp.begin() + 1, rDp.end())을 사용하여 rDp를 원래 순서로 되돌린다.
최종적으로 resultCount를 이용하여 dp[i] + rDp[i]의 최댓값을 구하고, 한 번 중복된 원소를 제거하기 위해 -1을 한 결과를 출력한다.
[소스 코드]
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
vector<int> dp;
vector<int> rDp;
vector<int> arr;
vector<int> arr2;
int N;
void Input() {
cin >> N;
arr.resize(N + 1);
dp.resize(N + 1,1);
rDp.resize(N + 1,1);
for (int i = 1; i <= N; i++) {
cin >> arr[i];
}
arr2 = arr;
reverse(arr2.begin()+1, arr2.end());
}
void Game_Start() {
for (int i = 1; i <= N; i++) {
for (int k = 1; k < i; k++) {
if (arr[i] > arr[k]) {
dp[i] = max(dp[i], dp[k] + 1);
}
if (arr2[i] > arr2[k]) {
rDp[i] = max(rDp[i], rDp[k] + 1);
}
}
}
reverse(rDp.begin() + 1, rDp.end());
int resultCount = -1;
for (int i = 1; i <= N; i++) {
resultCount = max(resultCount, rDp[i] + dp[i]);
}
cout << resultCount-1;
}
int main(void) {
Input();
Game_Start();
}
'백준 > 동적프로그래밍' 카테고리의 다른 글
백준 2133 c++ "타일 채우기" -PlusUltraCode- (0) | 2025.03.11 |
---|---|
백준 14002 c++ "가장 긴 증가하는 부분 수열 4" -PlusUltraCode- (0) | 2025.03.10 |
백준 2293 c++ "동전 1" -PlusUltraCode- (0) | 2025.03.09 |
백준 14728 c++ "벼락치기" -PlusUltraCode- (0) | 2025.03.08 |
백준 4811 c++ "알약" -PlusUltraCode- (0) | 2025.03.06 |