11053번: 가장 긴 증가하는 부분 수열
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이
www.acmicpc.net
이 문제는 앞의 결과가 뒤의 결과와 관련이 있으므로 규칙을 찾아서 점화식을 만들어서 푸는 DP문제이다.
n을 하나씩 증가시켜가며 점화식을 세운다.
n = 1 일 때는 자기 자신 뿐이므로 가장 긴 증가하는 부분 수열의 길이는 1이다.
n >= 2 일 때는 만약 앞에 자기 자신보다 낮은 숫자가 있다면, 해당 숫자까지로 이루어진 부분수열로 만들수 있는 가장 긴 증가하는 부분수열의 뒤에 자기 자신을 붙여서 더 큰 증가하는 부분수열을 만들 수 있으므로 해당 지점에 길이값 + 1 만큼의 길이를 가질 수 있다.
코드로 구현하면 다음과 같다.
#include <iostream>
using namespace std;
int max(int a, int b) { return a > b ? a : b; }
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int N;
int max_val = 0;
int arr[1000] = { 0, };
int dp[1000] = { 0, };
cin >> N;
for (int i = 0; i < N; i++) { cin >> arr[i]; }
for (int j = 0; j < N; j++) {
for (int i = j - 1; i >= 0; --i) {
if (arr[j] > arr[i]) dp[j] = max(dp[j], dp[i] + 1);
}
}
for (int i = N - 1; i >= 0; --i) max_val = max(max_val, dp[i]);
cout << max_val + 1;
return 0;
}
만약 당신이 이 문제의 반례를 찾다가 이 블로그를 방문했다면
3
3 1 2
를 입력해보자. 답은 2다. 만약 dp배열의 값이 0으로 초기화 되어있는 상태에서 dp[0] = 1을 주고 이중포문을 돌면서
if (arr[j] > arr[i]) dp[j] = max(dp[j], dp[i] + 1);
위와 같은 방법으로 dp값을 갱신시켜줬다면, 아마 답이 1이 나올 것이다. 그 어떤 값도 arr[0]보다 크지 않기 때문에 dp[0]은 무시된다. 따라서 모든 값을 1로 초기화 시켜주고 dp를 돌리던지 아니면 위의 코드처럼 아예 dp[0] = 0으로 두고 값을 구한 뒤 (max_val + 1) 을 해주면 된다.
'컴퓨터 사이언스 > 1고리즘' 카테고리의 다른 글
백준 1967 : 트리의 지름 (0) | 2020.12.18 |
---|---|
백준 11054 : 가장 긴 바이토닉 부분 수열 (0) | 2020.12.15 |
백준 5427 : 불 (0) | 2020.12.15 |
백준 4179 : 불! (0) | 2020.12.15 |
백준 2206 : 벽 부수고 이동하기 (0) | 2020.12.13 |