Count the number of subsequences of a given array so that their sum is less than or equal to a given number?

I have an array of ninteger values ​​and a given number S.

1<=n<=30

I want to find the total number of subsequences for which the sum of the elements of the subsequence is less S. For example: let n=3, S=5and the elements of the array will be like {1,2,3}, then its complete subsequences will be 7as -

{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}

but the required subsequences are:

{1},{2},{3},{1,2},{1,3},{2,3}

that is, it is {1,2,3}not accepted, because its sum of elements (1+2+3)=6, which is greater than Sthat 6>S. Others are taken because for other elements of the subsequence the sum is less S. Thus, the total number of possible subsequences will be 6. So my answer is tally that 6.

I tried a recursive method, but its temporary complexity 2^n. Please help us do this in polynomial time.

+4
source share
2 answers

(), , (, , , ). , nS . . , : - n, - "" S, .. S, M. , n 2^M.

, A. n S. , A[i][j] - , i j. , A , .. A[n][S] (, 1).

A[i][j]. , i ith, . , , A[i-1][j]. , , A[i-1][j-v[i]], v[i] - i- . , , i- , j-v[i]. , , , j- , . , (: i, 1 j):

std::vector<int> elements{1,2,3};
int S = 5;
auto N = elements.size();
std::vector<std::vector<int>> A;
A.resize(N);
for (auto& v : A) {
    v.resize(S+1);  // 1 based indexing for j/S, otherwise too annoying
}

// Number of subsequences using only first element is either 0 or 1
for (int j = 1; j != S+1; ++j) {
    A[0][j] = (elements[0] <= j);
}

for (int i = 1; i != N; ++i) {
    for (int j = 1; j != S+1; ++j) {
        A[i][j] = A[i-1][j];  // sequences that don't use ith element
        auto leftover = j - elements[i];
        if (leftover >= 0) ++A[i][j];  // sequence with only ith element, if i fits
        if (leftover >= 1) {  // sequences with i and other elements
            A[i][j] += A[i-1][leftover];
        }
    }
}

, A[N-1][S] 6 . , ( /, 1-, ).

+2

. .

" SUM <= K" .

, O (N * K),

N - , K - .

int countSubsets (int set[], int K) {
    int dp[N][K];

    //1. Iterate through all the elements in the set.
    for (int i = 0; i < N; i++) {
        dp[i][set[i]] = 1;

        if (i == 0) continue;

        //2. Include the count of subsets that doesn't include the element set[i]
        for (int k = 1; k < K; k++) {
            dp[i][k] += dp[i-1][k];
        }

        //3. Now count subsets that includes element set[i]
        for (int k = 0; k < K; k++) {
            if (k + set[i] >= K) {
                break;
            }
            dp[i][k+set[i]] += dp[i-1][k];
        }
    }
    //4. Return the sum of the last row of the dp table.
    int count = 0;
    for (int k = 0; k < K; k++) {
        count += dp[N-1][k];
    }
    // here -1 is to remove the empty subset
    return count - 1;
}       
-1

Source: https://habr.com/ru/post/1676718/


All Articles