C++ 코딩테스트 강좌, 부녀회장이 될 테야

문제 설명

“부녀회장이 될 테야” 문제는 아파트의 층과 호수에 따라 사람의 수를 계산하는 문제입니다.
주어진 층의 인덱스와 호수의 인덱스를 통해 몇 명이 거주하는지를 파악해야 합니다.
이 문제의 핵심은 피라미드 구조를 활용하여 각 층에서의 거주자 수를 계산하는 것입니다.

문제 이해하기

어느 아파트에 거주하는 사람의 수를 정의하는 규칙은 다음과 같습니다.
0층(i=0)의 경우, i호는 항상 1명입니다.
1층(i=1)에서는 i호가 1명에서 시작해, 위층의 모든 호수에 해당하는 사람의 수를 합산하여 나타납니다.

즉, f(n, k)는 n층 k호의 사람 수를 나타내면, 다음과 같은 재귀 방정식을 세울 수 있습니다:

f(n, k) = f(n-1, 1) + f(n-1, 2) + ... + f(n-1, k)

이 규칙을 바탕으로, n층 k호에 거주하는 사람 수는 (n-1)층 1호부터 k호까지의 합입니다.

문제 풀이 접근법

1. **기본 재귀 함수 구현**: 문제를 단순하게 풀기 위해, 재귀적으로 많은 호출이 발생하는 방법을 사용할 수 있습니다.
2. **동적 프로그래밍 활용**: 재귀적인 접근 방식은 동일한 값을 여러 번 호출할 수 있어 비효율적입니다.
세부적인 결과를 저장하는 메모이제이션(또는 다이나믹 프로그래밍)을 통해 성능을 개선할 수 있습니다.

이 문제는 층과 호수를 기반으로 테이블을 생성하여, 모든 계산된 값들을 저장할 수 있습니다.

C++ 코드 구현

아래의 코드는 동적 프로그래밍을 사용하여, 주어진 층과 호수의 사람 수를 계산하는 방식입니다:


#include <iostream>
#include <vector>

using namespace std;

int main() {
    int T; // 테스트 케이스 수
    cin >> T;
    
    while (T--) {
        int k, n; // k: 호수, n: 층
        cin >> k >> n;
        
        vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));

        // 0층 초기화
        for (int i = 1; i <= k; ++i) {
            dp[0][i] = 1; // 0층 i호에는 항상 1명
        }

        // DP 테이블 구성
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= k; ++j) {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }

        // 결과 출력
        cout << dp[n][k] << endl;
    }
    
    return 0;
}

시간 복잡도 분석

위의 구현 방식은 T개의 테스트 케이스에 대해 각각 n층 k호까지 계산하므로, 최악의 경우 O(n * k)의 시간 복잡도를 가집니다.
구현된 동적 프로그래밍 방식은 공간 복잡도 또한 O(n * k)를 요구합니다.

결론

“부녀회장이 될 테야” 문제는 문제의 규칙을 이해하고, 적절한 알고리즘을 선택해 구현함으로써 효율적으로 해결할 수 있습니다.
C++의 동적 프로그래밍 기법을 통해 성능을 극대화할 수 있으며, 이러한 접근은 다양한 유사한 문제를 풀 때에도 유용하게 사용할 수 있습니다.

추가 문제 및 연습

문제를 더 깊이 이해하고 싶다면, 다음과 같은 변형 문제를 시도해보는 것을 추천합니다:

  • 층의 수를 고정하고 호수를 변화시키기
  • 층과 호수를 반대로 바꿔서 문제를 설정하기
  • 기존의 DP 테이블을 최적화하여 공간 복잡도 줄이기