[DP]백준2631번 줄세우기

업데이트:

백준2631 줄세우기

_2021-03-12__12 46 33

이 문제는 LIS(최장 증가 수열) 알고리즘을 이용하여 풀 수 있는 문제다.

나는 이 방법을 떠올리지 못해 한참을 고민했다.

LIS는 주어진 수열에서 증가하는 최대 길이의 수열을 찾는 알고리즘이다.

이 알고리즘은 DP로 구현되며, 현재의 인덱스보다 작은 수들을 세는 방법과 비슷하다.

백준의 LIS 문제에 대해서는 백준11053 가장 긴 증가하는 부분수열 를 참고하면 된다.

최장 증가 수열 알고리즘의 풀이 방법을 이해하기 위해 가장 좋은 설명은

“자신보다 작은 애들을 찾고, 그 작은 애들 중에 자기보다 작은게 제일 많았던 애의 값 + 1을 자신의 값으로 취하는 것.” 정도가 될 것 같다.

줄 서 있는 아이들 수열에서 최장 증가 수열을 찾는다.

3 7 5 2 6 1 4

에서 최장 증가 수열은 3, 5 ,6 으로 길이 3이다.

문제에서 예시로 든 이동하는 아이들은 4, 7, 1, 2 이다.

즉, 최장 증가 수열에 속하지 않는 아이들이 움직인다.

수열에서 최장 증가 수열을 찾았다는 것은, 찾은 수열이 전체 수열 내에서 가장 큰 증가하는 수열이라는 뜻이다.

따라서 해당 최장 증가 수열을 뼈대로 두고 나머지 아이들을 이동시켜 정렬하는 것이 최소로 아이들을 움직이는 경우이다.

#include <iostream>

using namespace std;

int arr[205];
int dp[205];

int main(){
    int N;
    cin >> N;
    
    
    for(int i=1;i<=N;i++){
        cin >> arr[i];
        dp[i] = 1;
    }
    // LIS
    dp[1] = 1;
    for(int i=2;i<=N;i++){
        int tmp = 0;
        for(int j=1;j<i;j++){
            if(arr[j] < arr[i] ){
                if(dp[j] > tmp){
                    tmp = dp[j];
                }
            }
        }
        dp[i] = tmp + 1;
    }
    int answer = 0;
    for(int i=1;i<=N;i++){
        if(dp[i] > answer )answer = dp[i];
    }
    cout << N - answer;
    return 0;
}

카테고리:

업데이트:

댓글남기기