알고리즘 부셔버렷/ProblemSolving

[BOJ] 백준 2631 줄 세우기 (문제풀이, 코드 c++)

Unagi_zoso 2023. 1. 1. 23:51

 

  문제 설명

 

 

본 문제는 백준의 2631번 문제 줄 세우기 문제입니다.

 

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

 

중복 없는 연속된 수들을 최대한 적게 숫자를 이동시켜 오름차순으로 정렬하는데 그 때의 이동횟수를 구하는 문제 입니다.

 

 

 

  해결 과정

 

이 문제를 해결하는데는 다음과 같은 요소를 알아야합니다.

 

증가하는 부분수열 중 가장 큰 것을 구하고 부분수열에 해당되는 않는 숫자들을 옮기면 가장 적은 횟수로

정렬이 가능하다는 것 입니다.

 

문제에서 사용된 예시입니다.

 

3 7 5 2 6 1 4

 

증가하는 부분수열 중 가장 큰 것 { 3, 5, 6 } 이 숫자들은 고정해둔 채

나머지 7, 2, 1, 4를 움직이는 것 입니다.

 

그렇기에 답은 7 - 3 = 4가 됩니다.

 

증가하는 부분수열 중 가장 큰 것을 구하기 위해선

문제의 특성 상 N이 200으로 작아 brute force 방식으로 접근하여도 괜찮습니다.

 

 

이중 반목문으로 첫 인덱스로 전체를 순회할 때 현재 인덱스(i)가 이전의 인덱스(j) 보다 크고

위 조건에 성립되는 이전의 인덱스 중 증가하는 부분수열의 크기가 가장 큰 것의 값을 가져와 1을 더한 값을

i번 째 증가하는 부분수열의 크기로 최신화 시킵니다.

 

 

 

  코드 전문

 

 

#include <iostream>
#include <algorithm>

using namespace std;

int dp[202];
int origin[202]; 

int main() {
    int n;
    cin >> n;

    for (int i = 0; i < n; ++i) 
        cin >> origin[i];

    int ans = -1;
    for (int i = 0; i < n; ++i) {
        dp[i] = 1;
        for (int j = i - 1; j >= 0; --j) 
            if (origin[i] > origin[j] && ((dp[j]+1) > dp[i])) 
                dp[i] = dp[j]+1;
        
        ans = max(ans, dp[i]);
    }

    cout << n - ans;
}

 

 

 

 

  느낀 점 (잡설 99% , 배운점 1%(많은 편))

 

 

DP를 사용해야한다는 느낌은 들었지만 증가하는 부분수열에 대한 부분이 빠르게 떠오르지 않았습니다.

많이 배운 것 같습니다. 감사합니다.

 

 

 

참고한 글 

 

https://yabmoons.tistory.com/197

 

 

긴 글 읽어주셔서 감사합니다. 

부족한 점이 있다면 부디 알려주시면 감사하겠습니다.