Как и другие заявленные, это проблема суммы подмножеств (которая является NP-полной), то есть вам нужен экспоненциальный алгоритм времени для ее решения.
Просто взглянув на свою функцию, вы вызываете RecursePart
один раз, каждый раз с len-1, а затем получаете for-loop
длины n
, что означает, что ваши вычисления равны O(n^2)
. Это, очевидно, не решит проблему O(2^n)
.
Ниже приведено рекурсивное решение, которое создает сумму подмножеств и пытается определить, достигли ли они цели. Если для текущего подмножества нет опции равной цели, «создание» текущего подмножества останавливается.
int RecursePart(int arr[], int len, int idx, int curr_sum, int target)
{
int count = 0;
// this subset is good
if (curr_sum == target)
return 1;
// the sum of the current subset exceeds target, no point in continuing
if (curr_sum > target || idx == len)
return 0;
count += RecursePart(arr, len, idx+1, curr_sum + arr[idx], target);
count += RecursePart(arr, len, idx+1, curr_sum, target);
return count;
}
Это мое предыдущее решение, которое создает все возможные подмножества, и подсчитываются те, которые соответствуют цели.
#include <iostream>
int Wrapper(int[], int, int);
int main() {
int arr[8] = {1,2,3,4,5,6,7,8};
std::cout << Wrapper(arr, 8, 11);
}
// counts the sum of a subset
int CountSet(int* arr, int* mask, int len)
{
int sum = 0;
for (int i=0; i < len; ++i)
{
if (mask[i])
{
sum += arr[i];
}
}
return sum;
}
int RecursePart(int arr[], int idx, int len, int* subset_mask, int target)
{
int count = 0;
if (idx == len)
{
if (CountSet(arr, subset_mask, len) == target)
return 1;
else
return 0;
}
// create the subset "without" me
subset_mask[idx] = 0;
count += RecursePart(arr, idx+1, len, subset_mask, target);
// now create the subset "with" me
subset_mask[idx] = 1;
count += RecursePart(arr, idx+1, len, subset_mask, target);
return count;
}
int Wrapper(int arr[], int len, int target) {
int* subset_mask = (int*)malloc(len*sizeof(int));
int res = RecursePart(arr, 0, len, subset_mask, target);
free(subset_mask);
return res;
}