Given a set of n numbers a sum up to M , and any K ≤ M , say whether there is a subset of the numbers such that they sum to K? We assume n might be as big as 1000, but M or K is not too big.
code
Remark. The original idea is to use a 2 dimensional array, where each column only depends on the previous column. By a programming trick we just need one column. But we need to write the j-loop in the reversed way to avoid messing things up.
The following code shows how to achieve this.
code
#include<bits/stdc++.h>
using namespace std;
// function to print the elements of subset that forms the given sum
void printSubset(int*arr,int n,int S,bool**table,int i,int j)
{
if(i<=0 || j<=0)
return;
if(table[i][j-1]) // the jth element was not taken for sure.
{
printSubset(arr,n,S,table,i,j-1);
}
else // the jth element was taken for sure.
{
cout<<arr[j-1]<<" ";
printSubset(arr,n,S,table,i-arr[j-1],j-1);
}
}
bool isSubsetSum(int *arr,int n,int S)
{
bool **table; // table of size S x n
table=new bool*[S+1];
for(int i=0;i<=S;i++)
table[i]=new bool[n+1];
// table[i][j] will be true if sum 'i' can be achieved using first j elements of the array.
//base cases
// from the first 0 elements you can never achieve any sum.
for(int i=0;i<=S;i++)
table[i][0]=false;
// 0 sum can be achieved by any number of elements.
for(int i=0;i<=n;i++)
table[0][i]=true;
for(int i=1;i<=S;i++)
for(int j=1;j<=n;j++)
{
table[i][j]=table[i][j-1];
if(i-arr[j-1]>=0)
table[i][j]=table[i][j] || table[i-arr[j-1]][j-1];
}
bool answer=table[S][n];
if(answer)
printSubset(arr,n,S,table,S,n);
for(int i=0;i<=S;i++)
delete table[i];
delete table;
return answer;
}
int main()
{
int n;
cout<<"Enter the number of elements of the array : ";
cin>>n;
int *arr;
arr=new int[n];
cout<<"Enter the elements of the array : ";
for(int i=0;i<n;i++)
cin>>arr[i];
int S;
cout<<"Enter the sum : ";
cin>>S;
cout<<endl<<isSubsetSum(arr,n,S)<<endl;;
return 0;
}
Remark. The original idea is to use a 2 dimensional array, where each column only depends on the previous column. By a programming trick we just need one column. But we need to write the j-loop in the reversed way to avoid messing things up.
The following code shows how to achieve this.
bool isSubsetSumOptimized(int*arr,int n,int S)
{
bool *table;
table=new bool[S+1];
table[0]=1;
for(int i=0;i<n;i++)
for(int j=S;j>=arr[i];j--)
table[j]=table[j]||table[j-arr[i]];
bool answer=table[S];
delete table;
return answer;
}
No comments:
Post a Comment