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