오늘의 알고리즘

[C++] 백준 1208 부분수열의 합 2

하늘하늘 . 2022. 11. 16. 01:38
#include <iostream>
#include <unordered_map>
 
int N = 0;
int S = 0;
int arr[41] = {};
std::unordered_map<int, int> subsum = {};
long long count = 0;
 
void rightSum(int mid, int sum) 
{
    if (mid == N)
    {
        ++subsum[sum];
        return;
    }
 
    rightSum(mid + 1, sum + arr[mid]);
    rightSum(mid + 1, sum);
}
 
void leftSum(int left, int sum) 
{
    if (left == N / 2)
    {
        count += subsum[S - sum];
        return;
    }
 
    leftSum(left + 1, sum + arr[left]);
    leftSum(left + 1, sum);
}
 
int main() 
{
    std::cin >> N >> S;
 
    for (int i = 0; i < N; ++i) 
    {
        std::cin >> arr[i];
    }
 
    rightSum(N / 2, 0);
    leftSum(0, 0);
 
    if (!S) 
        std::cout << count - 1;
 
    else 
        std::cout << count;
 
    return 0;
}
 

모든 것들을 다 합산할 경우 2의 40승으로 무조건 시간 초과입니다.

2의 20승을 반으로 나눠서 계산하고 왼쪽합과 오른쪽합이

S가 될 수 있도록 합이 (오른쪽합)sum + S - (왼쪽합)sum이면 됩니다.