2021. 4. 20. 00:03ㆍAlgorithm
문제링크
문제
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.
예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.
입력
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.
둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)
출력
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.
풀이
이 문제는 가장 긴 증가하는 부분 수열을 구하는 문제입니다.
DP에서 유명한 LIS(Longest Increasing SubSequence) 문제입니다.
증가하는 수열을 구하려면 현재와 이전 값을 비교해서 더 큰 값인 경우 길이를 하나씩 늘릴 수 있습니다.
문제에 있는 예제로 어떻게 동작하는지 알아보도록 하겠습니다.
초기값
입력으로 주어진 수열은 A 배열에 저장하고 부분수열의 길이를 D 배열에 저장하도록 하겠습니다.
모든 값은 그 자체만으로도 길이가 1인 수열입니다.
따라서, D 배열에 1로 초기화합니다.
A[2]까지의 부분수열
A[2] 기준으로 가장 긴 증가하는 수열의 길이를 구해보도록 하겠습니다.
A[2]와 A[1]을 비교하면 A[2] > A[1], 20 > 10으로 A[2]가 큽니다.
따라서, A[1]까지의 길이보다 1만큼 더 깁니다.
그러므로 D[1] + 1 = 2 = D[2]가 됩니다.
A[3]까지의 부분수열
A[3]은 A[1], A[2] 보다 크지 않습니다.
따라서, 증가하는 수열이 아니므로 D[3]은 그대로 유지합니다.
A[4]까지의 부분수열
A[4]은 A[1] ~ A[3]까지의 값과 비교하여 증가하는지 확인합니다.
A[4] > A[1]이므로 D[4] = D[1] + 1 = 2입니다.
A[4] > A[2]이므로 D[4] = D[2] + 1 = 3입니다.
A[4] > A[3]이므로 D[4] = D[3] + 1 = 2입니다.
이 중 가장 큰 값은 3이며, A[4] > A[2]가 되는 경우입니다.
즉, 이 부분수열은 A[1], A[2], A[4] = 10, 20, 30입니다.
A[5]까지의 부분수열
A[5]은 A[1] ~ A[4]까지의 값과 비교하여 증가하는지 확인합니다.
A[5] > A[1]이므로 D[5] = D[1] + 1 = 2입니다.
A[5]와 A[2]는 값이 같으므로 증가하는 수열이 아닙니다.
A[5] > A[3]이므로 D[5] = D[3] + 1 = 2입니다.
이 중 가장 큰 값은 2이며, A[5] > A[1] 또는 A[5] > A[3]이 되는 경우입니다.
즉, 이 부분수열은 A[1], A[5] 또는 A[3], A[5]로 2가지 경우가 존재합니다.
A[6]까지의 부분수열
A[6]은 A[1] ~ A[4]까지의 값과 비교하여 증가하는지 확인합니다.
A[6] > A[1]이므로 D[6] = D[1] + 1 = 2입니다.
A[6] > A[2]이므로 D[6] = D[2] + 1 = 3입니다.
A[6] > A[3]이므로 D[6] = D[3] + 1 = 2입니다.
A[6] > A[4]이므로 D[6] = D[4] + 1 = 4입니다.
A[6] > A[5]이므로 D[6] = D[5] + 1 = 3입니다.
이 중 가장 큰 값은 4이며, A[6] > A[4]인 경우입니다.
즉, 이 부분수열은 A[1], A[2], A[4], A[6] = 10, 20, 30, 50입니다.
A[i] 기준으로 A[0] ~ A[i-1]까지 값을 비교하고, 가장 길이가 긴 경우를 찾아서 그 길이에 1만큼 더 해주면 됩니다.
소스
A[i] 기준으로 A[0] ~ A[i-1]까지 확인하기 위하여 for문을 하나 더 만들어서 j 변수로 돌립니다.
A[i] > A[j]보다 크면 D[i] = D[j] + 1을 하면 됩니다.
그리고 D배열의 전체 값 중에서 가장 큰 값을 찾으면 답이 됩니다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main
{
static int N;
static int A[];
static int D[];
static private int Answer;
public static void main(String[] args) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.valueOf(br.readLine());
A = new int[N];
D = new int[N];
String input = br.readLine();
StringTokenizer st = new StringTokenizer(input);
for (int i = 0; i < N; i++)
{
A[i] = Integer.valueOf(st.nextToken());
D[i] = 1; // 1로 초기화
}
for (int i = 0; i < N; i++)
{
for (int j = 0; j < i; j++)
{
if (A[i] > A[j] && i > 0 && D[j]+1 > D[i])
{
D[i] = D[j] + 1;
}
}
}
// 최대값
for (int i = 0; i < N; i++)
{
Answer = Math.max(Answer, D[i]);
}
System.out.println(Answer);
// System.out.println(Arrays.toString(D));
}
}
'Algorithm' 카테고리의 다른 글
[백준/10844/Java] 쉬운계단수 (0) | 2021.04.26 |
---|---|
[백준/2193/Java] 이친수 (0) | 2021.04.22 |
[백준/2156/Java] 포도주 시식 (0) | 2021.04.16 |
[백준/1932/Java] 정수 삼각형 (0) | 2021.04.12 |
[백준/2579/Java] 계단 오르기 (0) | 2021.04.06 |