1 분 소요

가장 큰 증가하는 부분 수열 (백준 Silver 2)

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

LIS 중 ‘가장 합’이 큰 수열의 그 합을 구하는 문제

풀이 방식

점화식 정의
DP[n] : n을 포함하는 가장 큰 증가하는 부분 수열의 값

따라서 DP[n]은 n->0 까지 돌며
이전 노드 중
자신보다 ‘수열의 값’이 작은 노드를 찾고

DP[n] = max(DP[n], DP[Target] + 수열 N의 값)
을 적용하면 된다

이걸 1-> n까지 반복하며
마지막에 dp에서 max_element를 통해 최댓값을 구한다
(실제로는 각 요소들에 대한 반복문은 한번만 돌기에
시간 복잡도는 O(N^2)가 된다)

(재귀 * 재귀 외부에서 각 요소를 반복문)

(ex : dp[n] -> recur(target)인 경우
target은 n보다 작으며 이미 dp를 구해놓음)

제출 코드

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int recur(const vector<int>& vec, vector<int>& dp,int start)
{
	if (start < 0)
		return 0;

	if (dp[start] != 0)
		return dp[start];

	dp[start] = vec[start];
	
	for (int i = start - 1; i >= 0; i--)
	{
		if (vec[start] > vec[i])
		{
			// start가 자신 이전 위치에서
			// 자신보다 낮은값 발견 시,
			// 그 dp값을 자신에게 더함
			dp[start] = max(dp[start], recur(vec, dp, i) + vec[start]);
		}
	}

	return dp[start];
}

int main()
{
	int n;
	cin >> n;
	vector<int> vec(n);
	for (int i = 0; i < n; i++)
		cin >> vec[i];

	// 가장 '합'이 큰 LIS 의 합 구하기
	vector<int> dp(n);
	dp[0] = vec[0];

	// start = 0 ~ n까지 진행
	for (int i = 1; i < n; i++)
		recur(vec, dp, i);

	cout << *max_element(dp.begin(), dp.end());

	return 0;
}

결과

Image

컴파일 에러는 include를 하지 않았기에….
(max_element)

LIS 는 DP 강의를 들을 때
푸는 법을 기억해 놓았기에 다행히 어렵지 않게 풀 수 있었다

댓글남기기