mojo's Blog
[백준 14002] 가장 긴 증가하는 부분 수열 4 본문
문제 링크 => 14002번: 가장 긴 증가하는 부분 수열 4 (acmicpc.net)
14002번: 가장 긴 증가하는 부분 수열 4
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이
www.acmicpc.net
다이나믹 프로그래밍 문제 + 약간의 생각을 더 해서 풀어야하는 문제이다.
참고로 이문제는 N=1000 밖에 안되기 때문에, 이분탐색을 사용하지 않고 다이나믹 프로그래밍으로 해결이 가능하다.
그러나 문제는 가장 긴 증가하는 부분 수열을 특정지어서 값을 표현하는게 생각보다 쉽지는 않았던거 같다.
이 문제를 해결하기 위해서 vector<int> v를 선언하였고 가장 큰 길이가 되도록 하는 배열의 index를 하나 잡아서 1씩 작아지면서 동시에 길이 또한 1씩 작아지는지를 동시에 체크하여 vector 에다가 배열 값을 차례로 push하는 방식으로 접근했다.
예제를 통해 위 방법을 간단하게 살펴보도록 한다.
6
10 20 10 30 20 50
이때 길이는 [ 1, 2, 1, 3, 2, 4 ] 이다. (인덱스는 0, 1, 2, 3, 4, 5)
이때 다이나믹 프로그래밍을 거치면서 길이가 더 큰 인덱스를 그 이전의 길이가 되도록 하는 인덱스를 이어주도록 하였다. ( 1 => 0, 3 => 1, 4 => 2, 4 => 1, 5 => 3 )
그 후에 가장 길이가 긴 인덱스 5를 기준으로 잡고 이어지는 부분이 없을때까지 다음 과정을 반복한다.
(i) 5일때 => (arr[3] < arr[5]) && dp[3] + 1 == dp[5] 를 만족하므로 3을 기준으로 잡는다.
(ii) 3일때 => (arr[1] < arr[3]) && dp[1] + 1 == dp[3] 를 만족하므로 1을 기준으로 잡는다.
(iii) 1일때 => (arr[0] < arr[1]) && dp[0] + 1 == dp[1] 를 만족하므로 0을 기준으로 잡는다.
마지막으로 0일때 인덱스 0의 이전 길이가 되도록 하는 인덱스가 없으므로 이 과정을 마친다.
벡터 v에 저장된 해당 인덱스의 배열값들을 역순으로 출력하게 되면 최종 정답이 된다.
풀이 code
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <time.h>
#define INF 100000000
#define endl '\n'
using namespace std;
int arr[1000];
int dp[1000];
vector<int> v[1001];
void solve(int n) {
int res = 0, tmp=0;
for (int i = 0; i < n; i++) {
dp[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i] && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
v[i].push_back(j);
}
}
res = max(res, dp[i]);
if (res == dp[i]) tmp = i;
}
cout << res << endl;
vector<int> res_V;
res_V.push_back(arr[tmp]);
while (1) {
if (v[tmp].size() == 0) break;
int minNum = 1001;
for (int i = 0; i < v[tmp].size(); i++) {
int next = v[tmp][i];
if (next < tmp && dp[next]+1==dp[tmp]) {
minNum = next;
}
}
tmp = minNum;
res_V.push_back(arr[tmp]);
}
for (int i = res_V.size() - 1; i >= 0; i--) {
cout << res_V[i] << " ";
}
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
solve(n);
return 0;
}
'백준 > Dynamic Programming' 카테고리의 다른 글
[백준 2240] 자두나무 (0) | 2021.07.04 |
---|---|
[백준 2293] 동전 1 (0) | 2021.07.04 |
[백준 11055] 가장 큰 증가 부분 수열 (0) | 2021.07.02 |
[백준 11722] 가장 긴 감소하는 부분 수열 (0) | 2021.07.01 |
[백준 2193] 이친수 (0) | 2021.07.01 |