티스토리 뷰

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

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

import java.util.Scanner;

public class Main {

    static int N;
    static int[] nums;
    static int[] dp;

    public static void func() {
        for(int i = 0; i < N; i++) {
            dp[i] = 1;
            for(int j = 0; j < i; j++) {
                if(nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        nums = new int[N + 1];
        dp = new int[N + 1];
        for(int i = 0; i < N; i++) {
            nums[i] = sc.nextInt();
        }
        func();
        int max = 0;
        for(int i = 0; i < N; i++) {
            max = Math.max(max, dp[i]);
        }
        System.out.println(max);
    }
}

 

가장 증가하는 부분 수열(LIS, Longest Increasing Subsequence)

 

어떻게 풀어야 하는지 정말 막막했는데 막상 풀고나서 보니까 정말로 별거 아니었던 알고리즘이다..

 

dp[] 배열은 현재 인덱스에서 가능한 최대 증가 부분수열의 길이를 담는다.

 

예제 1 3 5 2 3 4 를 생각해보자

 

idx = 0

dp[idx] 의 최솟값은 1이다.

왜냐하면 부분수열의 길이가 최소 1(본인)이기 때문이다.

 for(int i = 0; i < N; i++) {
            dp[i] = 1;

idx = 1

idx = 1이다.

int j = 0; j < idx; j++ 반복문으로 idx가 증가할때마다 앞에 있는 dp 배열을 전부 탐색해볼 것이다.

 

nums[j] < nums[idx] 인 경우에만 체크한다.

증가하는 부분수열이기 때문에 수열에 마지막에 제일 큰 값이 와야하기 때문.

 

이 경우에 Math.max(dp[idx], dp[j] + 1)으로 최댓값을 저장한다.

(dp[j] 의 길이에 자신이 추가됨으로써 dp[j] + 1이 최댓값)

    public static void func() {
        for(int i = 0; i < N; i++) {
            dp[i] = 1;
            for(int j = 0; j < i; j++) {
                if(nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
        }
    }

 

이렇게 완성된 것이 LIS의 길이를 찾아내는 알고리즘이다 (O(N^2))

 

 

 

이렇게 보면 별거 아닌데 왜이렇게 어려웠는지 모르겠다.

 

유사한 문제로 #11722 가장 긴 감소하는 부분수열 문제가 있는데,

(https://www.acmicpc.net/problem/11722)

 

이건 그냥 수열을 뒤집어놓고 증가 부분수열 알고리즘을 적용하면 그대로 풀린다 :D

 

 

 

'알고리즘 > DP' 카테고리의 다른 글

프로그래머스 | N으로 표현 - java  (0) 2022.08.28
프로그래머스 | 정수 삼각형 - java  (0) 2022.08.26
[JAVA] # 2156 포도주 시식  (0) 2021.09.02
[JAVA] # 9465 스티커  (0) 2021.09.01
[JAVA] #1890 점프  (0) 2021.08.30
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함