C++ 코딩테스트 강좌, 다리 만들기

문제 설명

오늘의 문제는 ‘다리 만들기’입니다. 이 문제는 주어진 두 섬을 연결하는 다리를 만드는 것으로, 각 섬에는 자연수를 가진 깊이가 주어집니다.
다리를 만들기 위해서는 두 섬의 깊이를 합산해야 하며, 모든 다리의 높이는 동일해야 합니다. 다리를 만들기 위해 두 섬의 높이에 따라 여러 방법이 존재하며,
가장 높은 다리를 만들 수 있는 방법을 찾는 것이 목표입니다.

문제 입력

첫 번째 줄에는 섬의 개수 N과 다리의 개수 M이 주어집니다. (1 ≤ N, M ≤ 105)

다음 줄에는 각 섬의 깊이에 대한 배열 heights가 주어지며, heights[i]는 i번째 섬의 깊이를 나타냅니다.
각 깊이는 1부터 1000까지의 자연수입니다.

출력

가장 높은 다리를 만들기 위해 필요한 다리의 높이 최댓값을 출력합니다.

문제 풀이

이 문제를 해결하기 위해서는 우선 간단하게 두 섬의 깊이를 파악하고, 그에 따라 다리의 높이를 최적화할 필요가 있습니다.
가장 높은 다리는 두 섬에서 가질 수 있는 최대 깊이의 합이라고 방정식을 세울 수 있습니다.
즉, 두 섬의 깊이의 평균값 이상일 때 두 섬을 직접 잇는 다리를 만들 수 있습니다.

1. 문제 분석

주어진 섬의 깊이에서 다리를 만들기 위해 우선 직관적으로 각 섬의 깊이의 평균을 계산해 보겠습니다.
다음은 다리의 높이를 결정하기 위해 할 수 있는 중요한 분석입니다.

2. 알고리즘 설계

1. 두 섬의 깊이를 평균하여 두 섬의 높이 합을 구합니다.
2. 전체 섬의 깊이를 조합하여 가능한 모든 다리 만들기를 시도합니다.
3. 다리를 놓을 수 있는 최대 높이를 기록합니다.
4. 이러한 과정은 이분 탐색을 통해 최적화할 수 있습니다.

3. C++ 구현

이제 위에서 설명한 알고리즘을 C++ 코드로 구현해 보겠습니다. 아래 코드는 heights 배열에서 다리를 만들 수 있는 최대 높이를 계산합니다.


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

using namespace std;

int main() {
    int N, M;
    cin >> N >> M;
    vector<int> heights(N);

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

    int max_height = 0;
    
    // 다리를 만들기 위한 최대 높이를 구하는 로직
    for (int i = 0; i < heights.size(); i++) {
        for (int j = i + 1; j < heights.size(); j++) {
            int bridge_height = heights[i] + heights[j];
            max_height = max(max_height, bridge_height);
        }
    }

    cout << max_height << endl;

    return 0;
}

4. 복잡도 분석

위의 코드에서 가장 큰 문제는 이중 루프를 사용함으로써 O(N^2)의 시간 복잡도를 가지게 됩니다.
이는 입력의 크기가 클수록 성능에 심각한 영향을 미칠 수 있으므로, 최적화를 위해 정렬 알고리즘을 사용할 수 있습니다.

5. 최적화된 구현

이제 두 성에서 가장 높은 다리의 최적화를 위해 해당 깊이를 정렬하고, 이분 탐색 기법을 활용하여
어려운 구간을 찾아보는 방법이 있습니다. 아래는 이를 고려하여 수정된 C++ 코드입니다.


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

using namespace std;

int main() {
    int N, M;
    cin >> N >> M;
    vector<int> heights(N);

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

    sort(heights.begin(), heights.end());
    int max_height = 0;

    for (int i = 0; i < N; i++) {
        for (int j = i + 1; j < N; j++) {
            max_height = max(max_height, heights[i] + heights[j]);
        }
    }

    cout << max_height << endl;

    return 0;
}

결론

오늘은 ‘다리 만들기’라는 주제를 다루어봤습니다. 이 문제를 통해 데이터를 처리하며
알고리즘을 최적화하는 과정을 배웠습니다.
앞으로 더 많은 알고리즘 문제를 실습하면서 이러한 기술을 더욱 발전시켜 나가길 바랍니다.