1

I need to find a maximum size subset from a set of numbers which will have a given sum X.

I've found a solution which solves this:

// A Dynamic Programming solution for the
// subset sum problem+ maximal subset size.

#include <bits/stdc++.h>
using namespace std;

// Returns size of maximum sized subset
// if there is a subset of set[] with sum
// equal to given sum. It returns -1 if there
// is no subset with given sum.
int isSubsetSum(int set[], int n, int sum)
{
    // The value of subset[i][j] will be true if there
    // is a subset of set[0..j-1] with sum equal to i
    bool subset[sum + 1][n + 1];
    int count[sum + 1][n + 1];

    // If sum is 0, then answer is true
    for (int i = 0; i <= n; i++)
    {
        subset[0][i] = true;
        count[0][i] = 0;
    }
 
    // If sum is not 0 and set is empty,
    // then answer is false
    for (int i = 1; i <= sum; i++)
    {
        subset[i][0] = false;
        count[i][0] = -1;
    }

    // Fill the subset table in bottom up manner
    for (int i = 1; i <= sum; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            subset[i][j] = subset[i][j - 1];
            count[i][j] = count[i][j - 1];
            if (i >= set[j - 1])
            {
                subset[i][j] = subset[i][j] ||
                               subset[i - set[j - 1]][j - 1];

                if (subset[i][j])
                    count[i][j] = max(count[i][j - 1],
                                      count[i - set[j - 1]][j - 1] + 1);
            }
        }
    }

    return count[sum][n];
}
 
// Driver code
int main()
{
    int set[] = { 2, 3, 5, 10 };
    int sum = 20;
    int n = 4;
    cout << isSubsetSum(set, n, sum);
}

However that solutions provided output is maximum number of elements from the set that sum up to given sum X. I would also need to have the subset as well.

For example:

set[] = { 2, 3, 5, 7, 10, 15 }

sum = 10

The output will be 3 which is correct, but I would also know the subset which in this case would be {2, 3, 5}.

It is not obvious for me how to extract this as I don't fully understand the algorithm. I am working on C implementation, but if anyone can explain the algorithm then that would also help.

EDIT:

I've worked up some solution in standard C which works, but seems to have some problem.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct s_set {
    int indx; 
    int arr[15];
};

int main(int argc, char *argv[]) {
        int set[] = {2, 3, 5, 10, 7, 6, 1, 1};
        int sum= 10;
        int n=8;
        int i, j, index;
        
        bool subset[sum + 1][n + 1];  // [subset_sum][subset_size]
        int count[sum + 1][n + 1];
        s_set lset[sum + 1][n + 1];
        s_set element;
        
        // if sum is 0, then answer is true - edge case when user provides sum vaue of 0 so no subset can exists
        i = 0;
        for (i; i <= n; i++)
        {
            subset[0][i] = true;
            count[0][i] = 0;
        }
        
        // if sum is not 0 and set is empty, then answer is false - edge case when user provides empty set so no subset to be found
        i = 1;
        for (i; i <= sum; i++)
        {
            subset[i][0] = false;
            count[i][0] = -1;
        }
        
        // set indexes to 0
        i=0;
        for (i; i <= sum; i++)
        {
            lset[i][0].indx=0;
        }
        
        // fill the subset table in bottom up manner
        i = 1;
        for (i; i <= sum; i++) {    // column index
            j=1;
            for (j; j <= n; j++) { 
                subset[i][j] = subset[i][j - 1]; 
                count[i][j] = count[i][j - 1];
                lset[i][j]=lset[i][j - 1];
                if (i >= set[j - 1]) { 
                    subset[i][j] = subset[i][j] || subset[i - set[j - 1]][j - 1]; 
 
                    if (subset[i][j])
                        if ((count[i - set[j - 1]][j - 1] + 1) > count[i][j - 1]) {
                            count[i][j]=count[i - set[j - 1]][j - 1] + 1;
                            element=lset[i - set[j - 1]][j - 1];
                            index=element.indx;
                            element.arr[index]=set[j - 1];
                            element.indx=index+1;
                            lset[i][j]=element;
                        }
                        else
                        {
                            count[i][j]=count[i][j - 1];
                        }
                }
            }
        }
        
        printf("Maximum number of elements from set: %d \n", count[sum][n]);
        //printf("Maximum number of elements from set: %d \n", lset[sum][n].indx);
        
        i=0;
        printf("SET{");
        for (i;i<=count[sum][n]-1;i++) {
            printf(" %d ", lset[sum][n].arr[i]);
        }
        printf("}");
        
        return 0;
}

The problem is that if arr size in the struct s_set is too low then it will not work and will give return code 3221225477. I've gotten it to work by randomly increasing the number (40 seems to work fine), but I don't understand why does this have any effect. The index number which is used to write into arr variable should not go so high.

Working (arr size 40): enter image description here

Not working (arr size 10): enter image description here

rongard
  • 89
  • 7
  • *"I am working on C implementation"* -- not if you are using `cout`, which indicates C++. Then again, aside from that line (and its support: the non-standard header and `using namespace std`), the code is C-style, using variable-length arrays instead of `std::vector`. So.... tough to guess. Which language are you trying to use? Object-oriented C++ or procedure-oriented C? – JaMiT Sep 17 '22 at 11:04
  • *"if anyone can explain the algorithm then that would also help."* -- Seeking to understand code you've encountered is a Good Thing. You might benefit more from this question if you made this your focus. Make this more of an algorithm question than a language-specific one. Before going into the code, try to describe what it does. Use the code as a backup in case you interpreted it incorrectly (which would warrant keeping the language tag, in my opinion). – JaMiT Sep 17 '22 at 11:09
  • Hey, thanks. The code is not written by me but is copied from the source that I referenced. I will be doing it in standard C, this is just a starting point for me. In any case I don't think it matters that much if its C or C++, algorithm implementation should not change. Anyone who can explain to me how to extract the subset values can do it even in python for that matter. – rongard Sep 17 '22 at 11:25
  • Hmm... maybe change *"I am working on C implementation"* to *"I am working on a variation (in C) that returns the subset in addition to the size"* to clarify that even though the code is (technically) C++, your target language is C. – JaMiT Sep 17 '22 at 12:06
  • 1
    I assume this is some kind of homework task. So you solve it by finding some code on the net. You don't understand how the code works and come here to ask us.... Well, if want to learn how to program I'll suggest that you start out by writing your own code – Support Ukraine Sep 17 '22 at 13:03
  • @SupportUkraine thanks for the lecture, really needed that! – rongard Sep 19 '22 at 06:12

0 Answers0