728x90

문제

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


풀이

2025.01.13 - [분류 전체보기] - [C++] 다이나믹 프로그래밍

 

[C++] 다이나믹 프로그래밍

다이나믹 프로그래밍(Dynamic Programming)은 문제를 작은 하위 문제로 나누어 해결하고, 그 결과를 저장하여 중복 계산을 방지하는 기법, 최적 부분 구조와 중복된 하위 문제가 있는 문제에 적합 재

zenstudy.tistory.com

1. 문제 분석

F(0)이 호출될 때마다 0이 출력되고, F(1)이 호출될 때마다 1이 출력

문제는 F(n)을 계산할 때 총 몇 번 0과 1이 호출되는지를 구하는 것

재귀의 비효율성

단순히 재귀로 계산하면, 같은 값에 대해 중복 호출이 많이 발생하여 비효율적

  • F(5) 계산 시:
    • F(5)는 F(4)와 F(3)을 호출
    • F(4)는 F(3)과 F(2)를 호출
    • 이런 식으로 F(3) 같은 값이 반복적으로 호출, 이를 효율적으로 해결하기 위해 DP(메모이제이션) 사용

2. 다이나믹 프로그래밍 점화식 도출

피보나치 수열의 특성상, F(n)의 호출 횟수는 F(n-1)과 F(n-2)의 호출 횟수의 합

  • dp[i].first: F(i) 계산 시 0이 호출된 횟수
  • dp[i].second: F(i) 계산 시 1이 호출된 횟수

점화식

dp[i].first=dp[i−1].first+dp[i−2].firstdp[i].first = dp[i-1].first + dp[i-2].first dp[i].second=dp[i−1].second+dp[i−2].seconddp[i].second = dp[i-1].second + dp[i-2].second

  • dp[i-1]은 F(i-1)을 계산할 때 호출된 횟수
  • dp[i-2]은 F(i-2)을 계산할 때 호출된 횟수
  • 따라서, F(i)에서 0과 1이 호출된 횟수는 각각 F(i-1)과 F(i-2)의 호출 횟수를 더한 값

 


코드

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL);
    std::cout.tie(NULL);

    int t;
    cin >> t;

    vector<pair<int, int>> dp(41); 
    dp[0] = { 1, 0 }; // 0을 호출한 횟수, 1을 호출한 횟수
    dp[1] = { 0, 1 };

    for (int i = 2; i <= 40; i++) {
        dp[i].first = dp[i - 1].first + dp[i - 2].first; // 0의 호출 횟수
        dp[i].second = dp[i - 1].second + dp[i - 2].second; // 1의 호출 횟수
    }

    for (int i = 0; i < t; i++) {
        int n;
        cin >> n;
        cout << dp[n].first << " " << dp[n].second << endl;
    }

    return 0;
}

 

728x90