View

300x250

문제 링크

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

문제

반도체를 설계할 때 n개의 포트를 다른 n개의 포트와 연결해야 할 때가 있다.

예를 들어 왼쪽 그림이 n개의 포트와 다른 n개의 포트를 어떻게 연결해야 하는지를 나타낸다. 하지만 이와 같이 연결을 할 경우에는 연결선이 서로 꼬이기 때문에 이와 같이 연결할 수 없다. n개의 포트가 다른 n개의 포트와 어떻게 연결되어야 하는지가 주어졌을 때, 연결선이 서로 꼬이지(겹치지, 교차하지) 않도록 하면서 최대 몇 개까지 연결할 수 있는지를 알아내는 프로그램을 작성하시오

입력

첫째 줄에 정수 n(1 ≤ n ≤ 40,000)이 주어진다. 다음 줄에는 차례로 1번 포트와 연결되어야 하는 포트 번호, 2번 포트와 연결되어야 하는 포트 번호, …, n번 포트와 연결되어야 하는 포트 번호가 주어진다. 이 수들은 1 이상 n 이하이며 서로 같은 수는 없다고 가정하자.

출력

첫째 줄에 최대 연결 개수를 출력한다.

조건

  • 시간 제한 : 2s
  • 메모리 제한 : 128MB

해설

문제를 잘 읽어보면 꼬이지 않게 포트를 선택하기 위해서는 선택한 포트의 번호가 계속 증가해야 한다. 이전에 선택한 포트 번호보다 작으면 줄이 꼬이기 때문이다. 이 점을 본다면 나열된 숫자 배열에서 선택한 원소들이 오름차순으로 정렬된 배열을 만드는 알고리즘이므로, LDS(가장 긴 증가하는 부분 수열) 알고리즘을 이용해 풀 수 있다는 것을 알 수 있다.

풀이

Input을 받아와 동적으로 메모리 공간을 생성하기 위해 vector를 사용해주었다. lds 벡터는 lds 알고리즘을 해결하기 위해 사용되는 벡터이다.

int N;
cin >> N;

vector<int> arr(N);
vector<int> lds;
for(int i = 0; i < N; i++) {
    cin >> arr[i];
}

우선 lds.back()이 메모리 참조에서 오류가 발생하지 않도록 하기 위해 첫번째 원소를 lds에 넣어주고 시작한다. lds 벡터의 최댓값보다 비교하는 원소가 크다면 push_back() 함수를 통해 넣어주고, 작다면 lds 벡터에서 해당 원소보다 큰 가장 작은 값을 찾아 자리를 대체한다. (작은 값일수록 더 긴 배열을 만들기에 유리하기 때문에) 이 알고리즘에 대해 더 자세하게 알고싶다면 LDS 알고리즘을 찾아보자. 마지막에 lds 벡터의 사이즈가 만들 수 있는 부분 수열의 최대길이이자, 선택할 수 있는 포트의 최대 개수이다.

// initial value
lds.push_back(arr[0]);

for(int i = 1; i < N; i++) {
    if(lds.back() < arr[i]) {
        lds.push_back(arr[i]);
    } else {
        int left = 0, right = lds.size();
        int mid;
        while(left <= right) {
            mid = (left+right)/2;
        
            if(lds[mid] <= arr[i]) {
                left=mid+1;
            } else {
                right=mid-1;
            }
        }
        lds[left] = arr[i];
    }
}

printf("%d\n", (int)lds.size());


코멘트

수학 활용 문제를 만난 기분이다. 뭔가 숨겨져있어서, 파헤쳐봤더니 LDS 문제네 ㅎㅎ. 이정도 난이도의 숨겨진 알고리즘을 찾아내는 문제라면 기분좋게 풀어낼 수 있을 것 같다.


코드

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main() {
    int N;
    cin >> N;
    
    vector<int> arr(N);
    vector<int> lds;
    for(int i = 0; i < N; i++) {
        cin >> arr[i];
    }
    
    // initial value
    lds.push_back(arr[0]);
    for(int i = 1; i < N; i++) {
        if(lds.back() < arr[i]) {
            lds.push_back(arr[i]);
        } else {
            int left = 0, right = lds.size();
            int mid;
            while(left <= right) {
                mid = (left+right)/2;
            
                if(lds[mid] <= arr[i]) {
                    left=mid+1;
                } else {
                    right=mid-1;
                }
            }
            lds[left] = arr[i];
        }
    }
    
    printf("%d\n", (int)lds.size());
    return 0;
}
320x100
Share Link
reply
반응형
«   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