/*
* This code demonstrates 2 techniques for finding all
* subsets of a given set: the backtracking algorithm heuristic
* and a technique based on binary couting. It also illustrates
* the backtracking heuristic to find all permutations.
*/
#include <iostream>
#include <vector>
#include <set>
#include <bitset>
#include <stl_algobase.h> //fix for bitset error in gcc
#include <math.h>
#include <algorithm>
//find all subsets using backtracking technique
void backTracking()
{
//size of set to find all subsets of
const int n = 15;
//bit vector whose position indicates
//whether or not the element at index
//is present for a given subset
vector<bool> A;
//put n+1 boolean slots into A
//(don't use index 0)
for(int i=0; i<=n; i++)
{
A.push_back(false);
}
//create initial set of all possibilities
set<bool> S;
S.insert(true);
S.insert(false);
//create vector of Sets of to remember S
//for each k
vector< set<bool> > Ses;
//put n sets of all initial possibilities
//for each k in Ses
//(**don't use index 0)
for(int i=0; i<=n; i++)
{
Ses.push_back(S);
}
//create empty set
S.clear();
//make Ses[n+1] = empty set because
//there are no legal values for
//that position
Ses.push_back(S);
int k=1;
bool ak = false;
while(k > 0)
{
while(!Ses[k].empty())
{
ak = *(--Ses[k].end());
Ses[k].erase(ak);
A[k] = ak;
if(k == n)
{
cout << "{";
for(int i=1; i<=k; i++)
{
//if(bits[j])
// cout << candidates[j] << " ";
cout << A[i] << " ";
}
cout << "\b}" << endl;
}
k++;
//if this new k is legal
//and S[k] is empty, refill it
//i.e. if there is a legal way to extend
//the partial solution, enumerate
//the possibilities
if(k <= n && Ses[k].empty())
{
Ses[k].insert(true);
Ses[k].insert(false);
}
}
k--; //backtrack
}
}
//find all permutations using backtracking technique
//beware, there are n! permutations for n
void backTracking2()
{
int num = 0;
//size of set to find all subsets of
const int n = 3;
//int vector whose position value
//stores the value for each permutation
vector<int> A;
//put n+1 int slots into A
//(don't use index 0)
for(int i=0; i<=n; i++)
{
A.push_back(0);
}
set<int> Aset;
//track which elements are in each A
vector<set<int> > As;
for(int i=0; i<=n; i++)
{
As.push_back(Aset);
}
//create initial set of all possibilities
set<int> S;
for(int i=1; i<=n; i++)
S.insert(i);
//create vector of Sets of to remember S
//for each k
vector< set<int> > Ses;
//put n sets of all initial possibilities
//for each k in Ses
Ses.push_back(S); // (**don't use index 0)
for(int i=1; i<=n; i++)
{
Ses.push_back(S);
S.erase(*(--S.end()));
}
//Ses[n+1] = empty set because
//there are no legal values for
//that position
Ses.push_back(S);
int k=1;
int ak = -1;
set<int> tempSet;
while(k > 0)
{
while(!Ses[k].empty())
{
ak = *(Ses[k].begin());
Ses[k].erase(ak);
A[k] = ak;
As[k] = As[k-1];
As[k].insert(ak);
if(k == n)
{
num++;
cout << "{";
for(int i=1; i<=k; i++)
{
cout << A[i] << " ";
}
cout << "\b}" << endl;
}
k++;
//if there is a legal way to extend
//the partial solution, enumerate
//the possibilities by updating the
//current Ses[k] which is the symmetric
//set difference of Ses[k] and As[k-1]
if(k <= n)
{
//enumerate all possible values
for(int i=1; i<=n; i++)
Ses[k].insert(i);
tempSet.clear();
//remove values present in previous
//partial solution
set_symmetric_difference(As[k-1].begin(), As[k-1].end(),
Ses[k].begin(), Ses[k].end(),
insert_iterator<set<int> >(tempSet, tempSet.begin()));
Ses[k].clear();
Ses[k] = tempSet;
}
}
k--; //backtrack
//keep As[k] in sync with A
As[k].erase(A[k]);
}
cout << "num permutations=" << num << endl;
}
//find all subsets using binary counting technique
void binaryCounting()
{
//Create all subsets via binary counting technique
//set size to do subsets of
const int n = 15;
int candidates[n];
//fill set with 1..n
for(int i=1; i<=n; i++)
candidates[i-1]=i;
bitset<n> bits;
vector<int> S(candidates, candidates+n);
for(int i=0; i<(pow(2,n)); i++)
{
//cout << (bits = i) << endl;
bits = i;
cout << "{";
for(int j=0; j<n; j++)
{
//if(bits[j])
// cout << candidates[j] << " ";
cout << bits[j] << " ";
}
//if(i!=0)
cout << "\b";
cout << "}" << endl;
}
}
int main()
{
//backTracking();
//binaryCounting();
backTracking2();
return 0;
}