1 분 소요

Intro

image

image

문제해결 및 소스코드

  • 이 문제는 가장 긴 증가하는 부분 수열문제, 가장 긴 감소하는 부분 수열문제를 응용하여 해결할 수 있는 문제이다.

  • 아직 접해보지 않았다면 먼저 해당 문제를 해결해보는것이 좋다.(11053번, 11722번)

  • 바이토닉 부분 수열이란, 수열이 주어졌을 때 어떤 수를 기준으로 좌측에서는 증가하고, 우측에서는 감소하는 수열이다.

/*                  예제1. 
    주어진 수열 { 1 5 2 1 4 3 4 5 2 1 } 에서, 가장 긴 바이토닉 부분수열은 
    { 1  2   3 4 5 2 1 } 로 길이가 7이다.
*/ 

  • 그렇다면 이 문제는 어떻게 해결해야될까? 예를들어 수열 { 1 2 3 2 1 } 이 있다고 하자.

  • 수열의 각 원소에 대하여 증가하는 부분수열과 감소하는 부분수열이 있을것이다.

  • 이때, 가장 긴 바이토닉 부분수열은 “각 원소에 대한 증감 부분수열의 길이의 최대합 - 1” 이 된다.

image

  • -1 을 해주는 이유는, 해당 원소에서의 증가 및 감소하는 부분수열 구하면서 중복 사용되었기 때문이다.
#include <iostream>
#include <algorithm>

using namespace std;

int arr[1001];				// 수열
int dp[1001];				// 증가하는 부분수열
int r_dp[1001];				// 감소하는 부분수열


int main()
{
	int n;
	cin >> n;

	// 입력
	for (int i = 1;i <= n;i++)
	{
		cin >> arr[i];
		dp[i] = 1;
		r_dp[i] = 1;
	}

	// 1. 각 원소의 가장 긴 증가하는 부분수열
	for (int i = 1;i <= n;i++)
	{
		for (int j = 1;j < i;j++)
		{
			if (arr[i] > arr[j]) dp[i] = max(dp[i], dp[j] + 1);
		}
	}

	// 2. 각 원소의 가장 긴 감소하는 부분수열
	for (int i = n;i > 0;i--)
	{
		for (int j = n;j > i;j--)
		{
			if (arr[i] > arr[j]) r_dp[i] = max(r_dp[i], r_dp[j] + 1);
		}
	}

	int ans = 0;
	// 3. 증가하는 부분수열과 감소하는 부분수열의 최대합 구하기
	for (int i = 1;i <= n;i++)
	{
		if (ans < dp[i] + r_dp[i]) ans = dp[i] + r_dp[i] - 1;		// 중복제거
	}

	cout << ans;
}

댓글남기기