Dynamic Programming - Counting paths in a subway system - c++
I have a network of stations in a subway system. The number of stations, the number of tickets I can travel between stations with, and which stations are connected to each other are given in a text file as input to the program. Which stations are connected to each other are kept in a 2D boolean matrix. I have to find the number of paths from station 0 and back to 0 that uses all of the tickets.
Here is one of the examples:
In that example, there are 7 stations and 5 tickets.
Starting and returning to 0, there are 6 paths:
0-1-2-3-4-0
0-1-5-3-4-0
0-1-6-3-4-0
0-4-3-6-1-0
0-4-3-5-1-0
0-4-3-2-1-0
I currently have a recursive solution to this that runs in O(N^k) (N represents the number of stations while k is the number of tickets), but I have to convert it to an iterative, dynamic programming solution in O(k*N^2) that works on any input.
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
// We will represent our subway as a graph using
// an adjacency matrix to indicate which stations are
// adjacent to which other stations.
struct Subway {
bool** connected;
int nStations;
Subway (int N);
private:
// No copying allowed
Subway (const Subway&) {}
void operator= (const Subway&) {}
};
Subway::Subway(int N)
{
nStations = N;
connected = new bool*[N];
for (int i = 0; i < N; ++i)
{
connected[i] = new bool[N];
fill_n (connected[i], N, false);
}
}
unsigned long long int callCounter = 0;
void report (int dest, int k)
{
++callCounter;
// Uncomment the following statement if you want to get a feel
// for how many times the same subproblems get revisited
// during the recursive solution.
cerr << callCounter << ": (" << dest << "," << k << ")" << endl;
}
/**
* Count the number of ways we can go from station 0 to station destination
* traversing exactly nSteps edges.
*/
unsigned long long int tripCounter (const Subway& subway, int destination, int nSteps)
{
report (destination, nSteps);
if (nSteps == 1)
{
// Base case: We can do this in 1 step if destination is
// directly connected to 0.
if (subway.connected[0][destination]){
return 1;
}
else{
return 0;
}
}
else
{
// General case: We can get to destinaiton in nSteps steps if
// we can get to station S in (nSteps-1) steps and if S connects
// to destination.
unsigned long long int totalTrips = 0;
for (int S = 0; S < subway.nStations; ++S)
{
if (subway.connected[S][destination])
{
// Recursive call
totalTrips += tripCounter (subway, S, nSteps-1);
}
}
return totalTrips;
}
}
// Read the subway description and
// print the number of possible trips.
void solve (istream& input)
{
int N, k;
input >> N >> k;
Subway subway(N);
int station1, station2;
while (input >> station1)
{
input >> station2;
subway.connected[station1][station2] = true;
subway.connected[station2][station1] = true;
}
cout << tripCounter(subway, 0, k) << endl;
// For illustrative/debugging purposes
cerr << "Recursive calls: " << callCounter << endl;
}
int main (int argc, char** argv)
{
if (argc > 1)
{
ifstream in (argv[1]);
solve (in);
}
else
{
solve (cin);
}
return 0;
}
I'm not looking for a solution. I am currently out of ideas and hoping someone can point me in the right direction. Since I'm required to implement a bottom-up approach for this, how would I start with developing a dynamic programming table using the smallest sub-problems?
You should construct an array T that for each step T[i] tells "how many paths are there between 0 and i".
For 0 steps, this array is:
[1, 0, 0, ... 0]
Then, for each step, do:
T_new[i] = sum{0<=j<n}(T[j] if there is an edge (i, j))
After k of those steps, T[0] will be the answer.
Here's a simple Python implementation to illustrate:
def solve(G, k):
n = len(G)
T = [0]*n
T[0] = 1
for i in xrange(k):
T_new = [
sum(T[j] for j in xrange(n) if G[i][j])
for i in xrange(n)
]
T = T_new
return T[0]
G = [
[0, 1, 0, 0, 1, 0, 0],
[1, 0, 1, 0, 0, 1, 1],
[0, 1, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0]
]
print solve(G, 5) #6
Dynamic programming works by recursively storing the previous subproblem result. In your case the subproblems consist of finding the number of all paths that, given a number of tickets k, can reach a station.
In the base case you have 0 tickets and thus the only station you can reach is station 0 with no paths. To kickstart the algorithm we assume that the null path is also a valid path.
At this point I would recommend you to get a piece of paper and try it out yourself first. The recursion you need is something like
set base case (i.e. station 0 == 1 null path)
for each ticket in [1;k]
stations = get the stations which were reached at the previous step
for each station in stations
spread the number of paths they were reached with to the neighbors
return the number of paths for station 0 with k tickets
The complete DP algorithm, minimizing the number of changes needed to integrate it into your code, follows
/**
* Count the number of ways we can go from station 0 to station destination
* traversing exactly nSteps edges with dynamic programming. The algorithm
* runs in O(k*N^2) where k is the number of tickets and N the number of
* stations.
*/
unsigned int tripCounter(const Subway& subway, int destination, int nSteps)
{
map<int, vector<int>> m;
for (int i = 0; i < nSteps + 1; ++i)
m[i].resize(subway.nStations, 0);
m[0][0] = 1; // Base case
for (int t = 1; t < m.size(); ++t) { // For each ticket
vector<int> reachedStations;
for (int s = 0; s < subway.nStations; ++s) { // For each station
if (m[t-1][s] > 0)
reachedStations.push_back(s); // Store if it was reached in the previous state
}
for (auto s : reachedStations) {
// Find adjacent stations
for (int adj = 0; adj < subway.nStations; ++adj) {
if (s == adj)
continue;
if (subway.connected[s][adj])
m[t][adj] += m[t-1][s];
}
}
}
return m[nSteps][0];
}
Complexity is as asked.
Make sure you understand the code before using it.
As you will learn iterating over subproblems is a common pattern in dynamic programming algorithms.
I suggest you consider the sub-problem:
DP[i][a] = number of paths from 0 to a using exactly i tickets
This is initialized with DP[0][0] = 1, and DP[0][a!=0] = 0.
You can get an update formula by considering all paths to a node:
DP[i][a] = sum DP[i-1][b] for all neighbours b of a
There are kN sub-problems, each taking O(N) to compute, so the total complexity is O(kN^2).
The final answer is given by DP[k][0].
Related
How to find all possible combinations of adding two variables, each attached to a multiplier, summing up to a given number (cin)?
In my situation, a lorry has a capacity of 30, while a van has a capacity of 10. I need to find the number of vans/lorries needed to transport a given amount of cargo, say 100. I need to find all possible combinations of lorries + vans that will add up to 100. The basic math calculation would be: (30*lorrycount) + (10*vancount) = n, where n is number of cargo. Output Example Cargo to be transported: 100 Number of Lorry: 0 3 2 1 Number of Van: 10 1 4 7 For example, the 2nd combination is 3 lorries, 1 van. Considering that lorries have capacity = 30 and van capacity = 10, (30*3)+(10*1) = 100 = n. For now, we only have this code, which finds literally all combinations of numbers that add up to given number n, without considering the formula given above. #include <iostream> #include <vector> using namespace std; void findCombinationsUtil(int arr[], int index, int num, int reducedNum) { int lorry_capacity = 30; int van_capacity = 10; // Base condition if (reducedNum < 0) return; // If combination is found, print it if (reducedNum == 0) { for (int i = 0; i < index; i++) cout << arr[i] << " "; cout << endl; return; } // Find the previous number stored in arr[] // It helps in maintaining increasing order int prev = (index == 0) ? 1 : arr[index - 1]; // note loop starts from previous number // i.e. at array location index - 1 for (int k = prev; k <= num; k++) { // next element of array is k arr[index] = k; // call recursively with reduced number findCombinationsUtil(arr, index + 1, num, reducedNum - k); } } void findCombinations(int n) { // array to store the combinations // It can contain max n elements std::vector<int> arr(n); // allocate n elements //find all combinations findCombinationsUtil(&*arr.begin(), 0, n, n); } int main() { int n; cout << "Enter the amount of cargo you want to transport: "; cin >> n; cout << endl; //const int n = 10; findCombinations(n); return 0; } Do let me know if you have any solution to this, thank you.
An iterative way of finding all possible combinations #include <iostream> #include <vector> int main() { int cw = 100; int lw = 30, vw = 10; int maxl = cw/lw; // maximum no. of lorries that can be there std::vector<std::pair<int,int>> solutions; // for the inclusive range of 0 to maxl, find the corresponding no. of vans for each variant of no of lorries for(int l = 0; l<= maxl; ++l){ bool is_integer = (cw - l*lw)%vw == 0; // only if this is true, then there is an integer which satisfies for given l if(is_integer){ int v = (cw-l*lw)/vw; // no of vans solutions.push_back(std::make_pair(l,v)); } } for( auto& solution : solutions){ std::cout<<solution.first<<" lorries and "<< solution.second<<" vans" <<std::endl; } return 0; }
We will create a recursive function that walks a global capacities array left to right and tries to load cargo into the various vehicle types. We keep track of how much we still have to load and pass that on to any recursive call. If we reach the end of the array, we produce a solution only if the remaining cargo is zero. std::vector<int> capacities = { 30, 10 }; using Solution = std::vector<int>; using Solutions = std::vector<Solution>; void tryLoad(int remaining_cargo, int vehicle_index, Solution so_far, std::back_insert_iterator<Solutions>& solutions) { if (vehicle_index == capacities.size()) { if (remaining_cargo == 0) // we have a solution *solutions++ = so_far; return; } int capacity = capacities[vehicle_index]; for (int vehicles = 0; vehicles <= remaining_cargo / capacity; vehicles++) { Solution new_solution = so_far; new_solution.push_back(vehicles); tryLoad(remaining_cargo - vehicles * capacity, vehicle_index + 1, new_solution, solutions); } } Calling this as follows should produce the desired output in all_solutions: Solutions all_solutions; auto inserter = std::back_inserter(all_solutions) tryLoad(100, 0, Solution{}, inserter);
move zeros in an array to the end
"The question comes under a broad category of "Array Transformation". This category is the meat of tech interviews. Mostly because arrays are such a simple and easy to use data structure. Traversal or representation doesn't require any boilerplate code and most of your code will look like the Pseudocode itself. The 2 requirements of the question are: Move all the 0's to the end of array. All the non-zero elements must retain their original order." My thinking: to find the zeros and exchange their positions with the last numbers /* int swap; int n=nums.size()-1; for(int i=0;i<nums.size();i--){ if(nums[i]==0){ swap = nums[i]; nums[i] = nums[n]; nums[n] = swap; n--; } } My input [0,1,0,3,12] Output [1,3,12,0,0] Diff Expected [1,3,12,0,0] And I did not know why the correct answer(the part) is : (int n = 0, cur = 0; cur < nums.size(); cur++) { if (nums[cur] != 0) { swap(nums[n++], nums[cur]); } } }
Can you use the standard library? std::stable_partition() makes it trivial. Something like std::stable_partition(nums.begin(), nums.end(), [](const auto &n){ return n != 0; }); For the question of how the solution in your post works: At the start of the first iteration, n is 0, cur is 0, and nums is [0,1,0,3,12]. nums[cur] is 0, so nothing happens. At the start of the second iteration, cur is 1, and nums[cur] is 1, so the swap and increment of n happens. Now n is 1, cur is 2, and nums is [1,0,0,3,12]. nums[cur] is 0, so nothing happens in the third iteration. In the fourth iteration, with cur now 3, a swap happens. So at the start of the the fifth iteration, n is 2, cur is 4, and nums is [1,3,0,0,12]. I'll leave it to you to work out what happens in that step. Basically, when n is not equal to cur, it's the index of a 0 element that can be swapped with a non-0 element that cur is the index of. This swapping eventually moves all 0's to the end.
My take on the problem, minimal std library usage. Probably not the most efficient, but it does the trick. #include "stdafx.h" #include <iostream> int main() { int src[] = { 0, 1, 0, 3, 0, 12 }; // Output: 1 3 12 0 0 0 check // = { 0, 3, 0, 1, 0, 0, 12, 0, 5 }; // Output: 3 1 12 5 0 0 0 0 0 check int n = sizeof(src) / sizeof(src[0]); for (int x = 0; x < n; x++) { for (int y = x + 1; y < n; y++) { if (src[x] == 0 && src[y] != 0) { int swap = src[x]; src[x] = src[y]; src[y] = swap; } } } for (int i = 0; i < n; i++) { std::cout << src[i] << " "; } return 0; }
Divide elements of a sorted array into least number of groups such that difference between the elements of the new array is less than or equal to 1
How to divide elements in an array into a minimum number of arrays such that the difference between the values of elements of each of the formed arrays does not differ by more than 1? Let's say that we have an array: [4, 6, 8, 9, 10, 11, 14, 16, 17]. The array elements are sorted. I want to divide the elements of the array into a minimum number of array(s) such that each of the elements in the resulting arrays do not differ by more than 1. In this case, the groupings would be: [4], [6], [8, 9, 10, 11], [14], [16, 17]. So there would be a total of 5 groups. How can I write a program for the same? Or you can suggest algorithms as well. I tried the naive approach: Obtain the difference between consecutive elements of the array and if the difference is less than (or equal to) 1, I add those elements to a new vector. However this method is very unoptimized and straight up fails to show any results for a large number of inputs. Actual code implementation: #include<cstdio> #include<iostream> #include<vector> using namespace std; int main() { int num = 0, buff = 0, min_groups = 1; // min_groups should start from 1 to take into account the grouping of the starting array element(s) cout << "Enter the number of elements in the array: " << endl; cin >> num; vector<int> ungrouped; cout << "Please enter the elements of the array: " << endl; for (int i = 0; i < num; i++) { cin >> buff; ungrouped.push_back(buff); } for (int i = 1; i < ungrouped.size(); i++) { if ((ungrouped[i] - ungrouped[i - 1]) > 1) { min_groups++; } } cout << "The elements of entered vector can be split into " << min_groups << " groups." << endl; return 0; }
Inspired by Faruk's answer, if the values are constrained to be distinct integers, there is a possibly sublinear method. Indeed, if the difference between two values equals the difference between their indexes, they are guaranteed to belong to the same group and there is no need to look at the intermediate values. You have to organize a recursive traversal of the array, in preorder. Before subdividing a subarray, you compare the difference of indexes of the first and last element to the difference of values, and only subdivide in case of a mismatch. As you work in preorder, this will allow you to emit pieces of the groups in consecutive order, as well as detect to the gaps. Some care has to be taken to merge the pieces of the groups. The worst case will remain linear, because the recursive traversal can degenerate to a linear traversal (but not worse than that). The best case can be better. In particular, if the array holds a single group, it will be found in time O(1). If I am right, for every group of length between 2^n and 2^(n+1), you will spare at least 2^(n-1) tests. (In fact, it should be possible to estimate an output-sensitive complexity, equal to the array length minus a fraction of the lengths of all groups, or similar.) Alternatively, you can work in a non-recursive way, by means of exponential search: from the beginning of a group, you start with a unit step and double the step every time, until you detect a gap (difference in values too large); then you restart with a unit step. Here again, for large groups you will skip a significant number of elements. Anyway, the best case can only be O(Log(N)).
I would suggest encoding subsets into an offset array defined as follows: Elements for set #i are defined for indices j such that offset[i] <= j < offset[i+1] The number of subsets is offset.size() - 1 This only requires one memory allocation. Here is a complete implementation: #include <cassert> #include <iostream> #include <vector> std::vector<std::size_t> split(const std::vector<int>& to_split, const int max_dist = 1) { const std::size_t to_split_size = to_split.size(); std::vector<std::size_t> offset(to_split_size + 1); offset[0] = 0; size_t offset_idx = 1; for (std::size_t i = 1; i < to_split_size; i++) { const int dist = to_split[i] - to_split[i - 1]; assert(dist >= 0); // we assumed sorted input if (dist > max_dist) { offset[offset_idx] = i; ++offset_idx; } } offset[offset_idx] = to_split_size; offset.resize(offset_idx + 1); return offset; } void print_partition(const std::vector<int>& to_split, const std::vector<std::size_t>& offset) { const std::size_t offset_size = offset.size(); std::cout << "\nwe found " << offset_size-1 << " sets"; for (std::size_t i = 0; i + 1 < offset_size; i++) { std::cout << "\n"; for (std::size_t j = offset[i]; j < offset[i + 1]; j++) { std::cout << to_split[j] << " "; } } } int main() { std::vector<int> to_split{4, 6, 8, 9, 10, 11, 14, 16, 17}; std::vector<std::size_t> offset = split(to_split); print_partition(to_split, offset); } which prints: we found 5 sets 4 6 8 9 10 11 14 16 17
Iterate through the array. Whenever the difference between 2 consecutive element is greater than 1, add 1 to your answer variable. ` int getPartitionNumber(int arr[]) { //let n be the size of the array; int result = 1; for(int i=1; i<n; i++) { if(arr[i]-arr[i-1] > 1) result++; } return result; } `
And because it is always nice to see more ideas and select the one that suites you best, here the straight forward 6 line solution. Yes, it is also O(n). But I am not sure, if the overhead for other methods makes it faster. Please see: #include <iostream> #include <string> #include <algorithm> #include <vector> #include <iterator> using Data = std::vector<int>; using Partition = std::vector<Data>; Data testData{ 4, 6, 8, 9, 10, 11, 14, 16, 17 }; int main(void) { // This is the resulting vector of vectors with the partitions std::vector<std::vector<int>> partition{}; // Iterating over source values for (Data::iterator i = testData.begin(); i != testData.end(); ++i) { // Check,if we need to add a new partition // Either, at the beginning or if diff > 1 // No underflow, becuase of boolean shortcut evaluation if ((i == testData.begin()) || ((*i) - (*(i-1)) > 1)) { // Create a new partition partition.emplace_back(Data()); } // And, store the value in the current partition partition.back().push_back(*i); } // Debug output: Copy all data to std::cout std::for_each(partition.begin(), partition.end(), [](const Data& d) {std::copy(d.begin(), d.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; }); return 0; } Maybe this could be a solution . . .
How do you say your approach is not optimized? If your is correct, then according to your approach, it takes O(n) time complexity. But you can use binary-search here which can optimize in average case. But in worst case this binary search can take more than O(n) time complexity. Here's a tips, As the array sorted so you will pick such a position whose difference is at most 1. Binary search can do this in simple way. int arr[] = [4, 6, 8, 9, 10, 11, 14, 16, 17]; int st = 0, ed = n-1; // n = size of the array. int partitions = 0; while(st <= ed) { int low = st, high = n-1; int pos = low; while(low <= high) { int mid = (low + high)/2; if((arr[mid] - arr[st]) <= 1) { pos = mid; low = mid + 1; } else { high = mid - 1; } } partitions++; st = pos + 1; } cout<< partitions <<endl; In average case, it is better than O(n). But in worst case (where the answer would be equal to n) it takes O(nlog(n)) time.
How can I find the maximum element in the left and right sides of an array?
I have a homework problem in C++ that I could (and did) solve, but not fast enough. So the problem goes like this: On a platform, there are n bars of equal width and height. It starts raining. Find out the quantity of water that fits in between the bars (Very bad enunciation , I know, it's better to look at the example). Examples: n = 6 bar lengths = {3, 0, 0, 2, 0, 4} Answer would be = 10 The cubes of water would "fill out" the empty space between the bars and I need the find the number of cubes: Explanation: Another example: n = 12 bar lengths = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1} Answer = 6 What I tried: For each spot in the array, I found the maximum height bar to the left of it and to the right of it and then I "filled" this spot with the minimum between the maximum to the left and the maximum to the right minus the height of the bar at the present spot: #include <iostream> using namespace std; int main() { int n, a[100001], i, j, volume=0, max_left, max_right; cin >> n; // Input the array for (i=0; i<n; i++) { cin >> a[i]; } // For each element (except the first and last) for (i=1; i<(n-1); i++) { max_left = max_right = a[i]; // Find the maximum to the left of it and to the right of it for (j=0; j<i; j++) { if (a[j] > max_left) { max_left = a[j]; } } for (j=(i+1); j<n; j++) { if (a[j] > max_right) { max_right = a[j]; } } // The quantity of water that fits on this spot is equal to // the minimum between the maxes, minus the height of the // bar in this spot volume += (min(max_left, max_right) - a[i]); } cout << volume; return 0; } The solution is good, I get the corrent results. But the speed is a problem. I believe the complexity of this solution is O(n^2), if I'm not mistaken. Now the problem has to be solved in O(n). The problem is: How can I find the maxes in both directions for each element in O(n)? Any help will be appreciated. Thanks!
Find the highest bar in the complete list. This gives to sub-ranges Before and After (both excluding the highest bar). Iterate over both sub-ranges (front to back for Before, back to front for After): Remember the highest bar you've found on the way, starting with 0. Add the difference of the current height to the result. Add both results. This works because once you've found the overall maximum height, all other heights for Front and Back are at least lower or equal than the maximum. This way you can skip searching in both directions and simply use the highest bar you've met so far. Both steps are O(n). Here is an example: #include <algorithm> #include <cassert> #include <iostream> #include <numeric> #include <vector> template <typename First, typename Last> int calcRange(First begin, Last end) { int max{0}; int result{0}; for (auto it = begin; it != end; ++it) { const auto current = *it; result += std::max(0, max - current); max = std::max(max, current); } return result; } int calc(const std::vector<int>& bars) { if (bars.size() <= 1) return 0; // find max = O(n) const auto maxIt = std::max_element(bars.cbegin(), bars.cend()); assert(maxIt != bars.cend()); // calculate left and right = O(n) const auto l = calcRange(bars.cbegin(), maxIt); const auto r = calcRange(bars.crbegin(), std::make_reverse_iterator(maxIt)); return l + r; } int main() { std::cout << calc({3, 0, 0, 2, 0, 4}) << std::endl; std::cout << calc({0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}) << std::endl; }
I have to say, that I really liked this question. This might give you an idea on how to solve this question. Basically, you are looking to leftmost and rightmost bar heights. Then you will raise the waterlevel to the minimum of both and compute the amount of water needed for this. Afterwards you can shrink the bars array and repeat the process. #include <iostream> #include <string> #include <vector> #include <algorithm> #include <numeric> int main() { std::vector<int> bars{ 3, 0, 0, 2, 0, 4 }; int waterCounter = 0; int waterLevel = 0; auto leftIter = bars.begin(); auto rightIter = bars.end() - 1; while (true) { if (leftIter == rightIter) break; auto newWaterLevel = std::min(*leftIter, *rightIter); if (newWaterLevel > waterLevel) { auto newRight = std::next(rightIter); auto size=std::distance(leftIter, newRight); auto waterInGaps = 0; for (auto iter=leftIter; iter!=newRight; iter++ ) { waterInGaps += *iter > newWaterLevel ? 0 : newWaterLevel-*iter; *iter = *iter>newWaterLevel?*iter:newWaterLevel; } waterCounter += waterInGaps; } while (leftIter!=rightIter) { if (*leftIter > newWaterLevel) break; std::advance(leftIter, 1); } while (rightIter!=leftIter) { if (*rightIter > newWaterLevel) break; std::advance(rightIter, -1); } waterLevel = newWaterLevel; } std::cout << waterCounter << std::endl; return EXIT_SUCCESS; }
Thanks a lot everyone, your ideas helped! As I am not that advanced, I couldn't (and didn't really know how to) use vectors, auto (this one seems like magic to me), templates and other things. If anyone is still interested, this is the code I used and I got 100 points on the site: #include <iostream> using namespace std; int main() { int n, a[100001], left_max[100001], right_max[100001]; int i, max_to_right, max_to_left, volume=0; cin >> n; for (i=0; i<n; i++) { // Input the array cin >> a[i]; // Directly find the "maximum to the left" of each element if (i == 0) { left_max[i] = max_to_left = a[i]; } else { if (a[i] > max_to_left) { max_to_left = a[i]; } left_max[i] = max_to_left; } } // Not the only thing left is to find the "maximum to the right" of each element for (i=(n-1); i>=0; i--) { if (i == (n-1)) { right_max[i] = max_to_right = a[i]; } else { if (a[i] > max_to_right) { max_to_right = a[i]; } right_max[i] = max_to_right; } // No need to have another loop afterwards, add to volume as we go if (i>0 && i<(n-1)) { volume += (min(left_max[i], right_max[i]) - a[i]); } } cout << volume; return 0; } I basically did the same thing, but faster. I found the maximum to the right and to the left of each element, but I found the maximum to the left of each element while reading the input and then with another loop I found the maximum of each element, but to the right. The website had a very similar solution, just a bit shorter.
I would start off by asking off a few questions which would get me close to a solution. Think of it this way, if you poured water into the structure above, the empty spots would only ever accumulate to the right or the left of the 'Highest bar'. Once you have that insight, now from left to the highest bar do the following, currbar_from_left = -1 and the current value set to start of the array. 1- if the currbar_from_left > current then currbar_from_left = current else ans = ans + (currbar - currbar_from_left) - add the difference to the answer since we know definately that this would accmulate compared to our anchor point(the highest bar) 2- now do another traversal, this time from right of the array to the highest point. currbar_from_right = -1 and current set to the last value in the array if the currbar_from_right > current then currbar_from_right = current else ans = ans + (currbar - curbar_from_right) 3- The ans is now the total empty cubes. You could combine steps 1 and 2 into a single loop with the conditions as they are but the above algorithm is more clear in terms of understanding. The following code demostrates this: int n, a[100001], i, j, volume = 0, max_left, max_right; cin >> n; // Input the array for (i = 0; i<n; i++) { cin >> a[i]; } // Maximum height in the array int maximum_bar = -1, maximum_index = -1; for (i = 0; i < n; i++) { if (a[i] > maximum_bar) { maximum_bar = a[i]; // where did i see it? maximum_index = i; } } //Left search, to the maximum_bar int left = -1; for (i = 0; i < maximum_index; i++) { if (a[i] > left) left = a[i]; else volume = volume + (left - a[i]); } //Right search, to the maximum_bar int right = -1; for (i = n - 1; i >= maximum_index; i--) { if (a[i] > right) right = a[i]; else volume = volume + (right - a[i]); } cout << volume; return 0;
Let's try a different approach. We can do this in a single pass from left to right, except for a special case at the end of the array. Consider that we're iterating from left to right, keeping track of what's the current water level. Each of these scenarios can happen: We reached a column that is higher than the water level; We reached a column that is lower than the water level; We reached a column that has the same height as the water level; The first one defines a new water level. For the two others, notice that to count the blocks, all we need to do is add water_level - height to the current total. This will only cause a problem once we reach the end. Consider this input, for instance: {2, 0, 0, 3, 0, 0} Notice that the water level on the two last items should be 0, but we have just set it to 3! To fix this, we simply discard the result of the last iteration (from 3 to the end) and do a reverse iteration from the end to that point. If this all sounds a bit tricky, you will see that the implementation is actually quite simple. Following is what I came up with: It uses some recursion to simplify things, and works on any pair of iterators: #include <iterator> // std::reverse_iterator template<typename It> int pass(It begin, It end) { if (end - begin <= 1) return 0; int result = 0; auto it = begin; while(++it != end) { // We keep track of the current water level by simply querying the begin iterator. if (*it <= *begin) { result += *begin - *it; } else { // We need to define a new water level. Let's just do a new pass, with the begin pointing to the new column. return result + pass(it, end); } } // If we got here, it means we reached the end. We should discard the result, and do a reverse pass instead return pass(std::reverse_iterator(end), std::reverse_iterator(begin)); } Use it like this: int main() { std::vector<int> v{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; std::cout << pass(v.begin(), v.end()); } // Output: 6
Power set of large set
I have to calculate power set of set which may have more elements upto 10^5. I tried an algo and the code below but it failed (I think cause large value of pow(2, size)). void printPowerSet(int *set, int set_size) { unsigned int pow_set_size = pow(2, set_size); int counter, j,sum=0; for(counter = 0; counter < pow_set_size; counter++) { for(j = 0; j < set_size; j++) { if(counter & (1<<j)) std::cout<<set[i]<<" "; } std::cout<<sum; sum=0; printf("\n"); } } Is there any other algorithm or how can I fix this one (if it is possible)?? OR Can you suggest me how to do it i.e. finding subset of large set. As pointed out in an answer it seems I'm stuck in X-Y problem. Basically, I need sum of all subsets of any set. Now if you can suggest me any other approach to solve the problem. Thank you.
Here is an algorithm which will print out the power set of any set that will fit in your computer's memory. Given enough time, it will print the power set of a set of length 10^5. However, "enough time" will be something like several trillion billion gazillion years. c++14 #include <iostream> #include <vector> #include <algorithm> using namespace std; #include <iostream> void printPowerset (const vector<int>& original_set) { auto print_set = [&original_set](auto first, auto last) -> ostream& { cout << '('; auto sep = ""; for ( ; first != last ; ++first, sep = ",") { cout << sep << original_set[(*first) - 1]; } return cout << ')'; }; const int n = original_set.size(); std::vector<int> index_stack(n + 1, 0); int k = 0; while(1){ if (index_stack[k]<n){ index_stack[k+1] = index_stack[k] + 1; k++; } else{ index_stack[k-1]++; k--; } if (k==0) break; print_set(begin(index_stack) + 1, begin(index_stack) + 1 + k); } print_set(begin(index_stack), begin(index_stack)) << endl; } int main(){ auto nums = vector<int> { 2, 4, 6, 8 }; printPowerset(nums); nums = vector<int> { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; printPowerset(nums); return 0; } expected results: first power set (4 items): (2)(2,4)(2,4,6)(2,4,6,8)(2,4,8)(2,6)(2,6,8)(2,8)(4)(4,6)(4,6,8)(4,8)(6)(6,8)(8)() second power set (10 items) (2)(2,4)(2,4,6)(2,4,6,8)(2,4,6,8,10)(2,4,6,8,10,12)(2,4,6,8,10,12,14)(2,4,6,8,10,12,14,16)(2,4,6,8,10,12,14,16,18)(2,4,6,8,10,12,14,16,18,20)(2,4,6,8,10,12,14,16,20)(2,4,6,8,10,12,14,18)(2,4,6,8,10,12,14,18,20)(2,4,6,8,10,12,14,20)(2,4,6,8,10,12,16)(2,4,6,8,10,12,16,18)(2,4,6,8,10,12,16,18,20)(2,4,6,8,10,12,16,20)(2,4,6,8,10,12,18)(2,4,6,8,10,12,18,20)(2,4,6,8,10,12,20)(2,4,6,8,10,14)(2,4,6,8,10,14,16)(2,4,6,8,10,14,16,18)(2,4,6,8,10,14,16,18,20)(2,4,6,8,10,14,16,20)(2,4,6,8,10,14,18)(2,4,6,8,10,14,18,20)(2,4,6,8,10,14,20)(2,4,6,8,10,16)(2,4,6,8,10,16,18)(2,4,6,8,10,16,18,20)(2,4,6,8,10,16,20)(2,4,6,8,10,18)(2,4,6,8,10,18,20)(2,4,6,8,10,20)(2,4,6,8,12)(2,4,6,8,12,14)(2,4,6,8,12,14,16)(2,4,6,8,12,14,16,18)(2,4,6,8,12,14,16,18,20)(2,4,6,8,12,14,16,20)(2,4,6,8,12,14,18)(2,4,6,8,12,14,18,20)(2,4,6,8,12,14,20)(2,4,6,8,12,16)(2,4,6,8,12,16,18)(2,4,6,8,12,16,18,20)(2,4,6,8,12,16,20)(2,4,6,8,12,18)(2,4,6,8,12,18,20)(2,4,6,8,12,20)(2,4,6,8,14)(2,4,6,8,14,16)(2,4,6,8,14,16,18)(2,4,6,8,14,16,18,20)(2,4,6,8,14,16,20)(2,4,6,8,14,18)(2,4,6,8,14,18,20)(2,4,6,8,14,20)(2,4,6,8,16)(2,4,6,8,16,18)(2,4,6,8,16,18,20)(2,4,6,8,16,20)(2,4,6,8,18)(2,4,6,8,18,20)(2,4,6,8,20)(2,4,6,10)(2,4,6,10,12)(2,4,6,10,12,14)(2,4,6,10,12,14,16)(2,4,6,10,12,14,16,18)(2,4,6,10,12,14,16,18,20)(2,4,6,10,12,14,16,20)(2,4,6,10,12,14,18)(2,4,6,10,12,14,18,20)(2,4,6,10,12,14,20)(2,4,6,10,12,16)(2,4,6,10,12,16,18)(2,4,6,10,12,16,18,20)(2,4,6,10,12,16,20)(2,4,6,10,12,18)(2,4,6,10,12,18,20)(2,4,6,10,12,20)(2,4,6,10,14)(2,4,6,10,14,16)(2,4,6,10,14,16,18)(2,4,6,10,14,16,18,20)(2,4,6,10,14,16,20)(2,4,6,10,14,18)(2,4,6,10,14,18,20)(2,4,6,10,14,20)(2,4,6,10,16)(2,4,6,10,16,18)(2,4,6,10,16,18,20)(2,4,6,10,16,20)(2,4,6,10,18)(2,4,6,10,18,20)(2,4,6,10,20)(2,4,6,12)(2,4,6,12,14)(2,4,6,12,14,16)(2,4,6,12,14,16,18)(2,4,6,12,14,16,18,20)(2,4,6,12,14,16,20)(2,4,6,12,14,18)(2,4,6,12,14,18,20)(2,4,6,12,14,20)(2,4,6,12,16)(2,4,6,12,16,18)(2,4,6,12,16,18,20)(2,4,6,12,16,20)(2,4,6,12,18)(2,4,6,12,18,20)(2,4,6,12,20)(2,4,6,14)(2,4,6,14,16)(2,4,6,14,16,18)(2,4,6,14,16,18,20)(2,4,6,14,16,20)(2,4,6,14,18)(2,4,6,14,18,20)(2,4,6,14,20)(2,4,6,16)(2,4,6,16,18)(2,4,6,16,18,20)(2,4,6,16,20)(2,4,6,18)(2,4,6,18,20)(2,4,6,20)(2,4,8)(2,4,8,10)(2,4,8,10,12)(2,4,8,10,12,14)(2,4,8,10,12,14,16)(2,4,8,10,12,14,16,18)(2,4,8,10,12,14,16,18,20)(2,4,8,10,12,14,16,20)(2,4,8,10,12,14,18)(2,4,8,10,12,14,18,20)(2,4,8,10,12,14,20)(2,4,8,10,12,16)(2,4,8,10,12,16,18)(2,4,8,10,12,16,18,20)(2,4,8,10,12,16,20)(2,4,8,10,12,18)(2,4,8,10,12,18,20)(2,4,8,10,12,20)(2,4,8,10,14)(2,4,8,10,14,16)(2,4,8,10,14,16,18)(2,4,8,10,14,16,18,20)(2,4,8,10,14,16,20)(2,4,8,10,14,18)(2,4,8,10,14,18,20)(2,4,8,10,14,20)(2,4,8,10,16)(2,4,8,10,16,18)(2,4,8,10,16,18,20)(2,4,8,10,16,20)(2,4,8,10,18)(2,4,8,10,18,20)(2,4,8,10,20)(2,4,8,12)(2,4,8,12,14)(2,4,8,12,14,16)(2,4,8,12,14,16,18)(2,4,8,12,14,16,18,20)(2,4,8,12,14,16,20)(2,4,8,12,14,18)(2,4,8,12,14,18,20)(2,4,8,12,14,20)(2,4,8,12,16)(2,4,8,12,16,18)(2,4,8,12,16,18,20)(2,4,8,12,16,20)(2,4,8,12,18)(2,4,8,12,18,20)(2,4,8,12,20)(2,4,8,14)(2,4,8,14,16)(2,4,8,14,16,18)(2,4,8,14,16,18,20)(2,4,8,14,16,20)(2,4,8,14,18)(2,4,8,14,18,20)(2,4,8,14,20)(2,4,8,16)(2,4,8,16,18)(2,4,8,16,18,20)(2,4,8,16,20)(2,4,8,18)(2,4,8,18,20)(2,4,8,20)(2,4,10)(2,4,10,12)(2,4,10,12,14)(2,4,10,12,14,16)(2,4,10,12,14,16,18)(2,4,10,12,14,16,18,20)(2,4,10,12,14,16,20)(2,4,10,12,14,18)(2,4,10,12,14,18,20)(2,4,10,12,14,20)(2,4,10,12,16)(2,4,10,12,16,18)(2,4,10,12,16,18,20)(2,4,10,12,16,20)(2,4,10,12,18)(2,4,10,12,18,20)(2,4,10,12,20)(2,4,10,14)(2,4,10,14,16)(2,4,10,14,16,18)(2,4,10,14,16,18,20)(2,4,10,14,16,20)(2,4,10,14,18)(2,4,10,14,18,20)(2,4,10,14,20)(2,4,10,16)(2,4,10,16,18)(2,4,10,16,18,20)(2,4,10,16,20)(2,4,10,18)(2,4,10,18,20)(2,4,10,20)(2,4,12)(2,4,12,14)(2,4,12,14,16)(2,4,12,14,16,18)(2,4,12,14,16,18,20)(2,4,12,14,16,20)(2,4,12,14,18)(2,4,12,14,18,20)(2,4,12,14,20)(2,4,12,16)(2,4,12,16,18)(2,4,12,16,18,20)(2,4,12,16,20)(2,4,12,18)(2,4,12,18,20)(2,4,12,20)(2,4,14)(2,4,14,16)(2,4,14,16,18)(2,4,14,16,18,20)(2,4,14,16,20)(2,4,14,18)(2,4,14,18,20)(2,4,14,20)(2,4,16)(2,4,16,18)(2,4,16,18,20)(2,4,16,20)(2,4,18)(2,4,18,20)(2,4,20)(2,6)(2,6,8)(2,6,8,10)(2,6,8,10,12)(2,6,8,10,12,14)(2,6,8,10,12,14,16)(2,6,8,10,12,14,16,18)(2,6,8,10,12,14,16,18,20)(2,6,8,10,12,14,16,20)(2,6,8,10,12,14,18)(2,6,8,10,12,14,18,20)(2,6,8,10,12,14,20)(2,6,8,10,12,16)(2,6,8,10,12,16,18)(2,6,8,10,12,16,18,20)(2,6,8,10,12,16,20)(2,6,8,10,12,18)(2,6,8,10,12,18,20)(2,6,8,10,12,20)(2,6,8,10,14)(2,6,8,10,14,16)(2,6,8,10,14,16,18)(2,6,8,10,14,16,18,20)(2,6,8,10,14,16,20)(2,6,8,10,14,18)(2,6,8,10,14,18,20)(2,6,8,10,14,20)(2,6,8,10,16)(2,6,8,10,16,18)(2,6,8,10,16,18,20)(2,6,8,10,16,20)(2,6,8,10,18)(2,6,8,10,18,20)(2,6,8,10,20)(2,6,8,12)(2,6,8,12,14)(2,6,8,12,14,16)(2,6,8,12,14,16,18)(2,6,8,12,14,16,18,20)(2,6,8,12,14,16,20)(2,6,8,12,14,18)(2,6,8,12,14,18,20)(2,6,8,12,14,20)(2,6,8,12,16)(2,6,8,12,16,18)(2,6,8,12,16,18,20)(2,6,8,12,16,20)(2,6,8,12,18)(2,6,8,12,18,20)(2,6,8,12,20)(2,6,8,14)(2,6,8,14,16)(2,6,8,14,16,18)(2,6,8,14,16,18,20)(2,6,8,14,16,20)(2,6,8,14,18)(2,6,8,14,18,20)(2,6,8,14,20)(2,6,8,16)(2,6,8,16,18)(2,6,8,16,18,20)(2,6,8,16,20)(2,6,8,18)(2,6,8,18,20)(2,6,8,20)(2,6,10)(2,6,10,12)(2,6,10,12,14)(2,6,10,12,14,16)(2,6,10,12,14,16,18)(2,6,10,12,14,16,18,20)(2,6,10,12,14,16,20)(2,6,10,12,14,18)(2,6,10,12,14,18,20)(2,6,10,12,14,20)(2,6,10,12,16)(2,6,10,12,16,18)(2,6,10,12,16,18,20)(2,6,10,12,16,20)(2,6,10,12,18)(2,6,10,12,18,20)(2,6,10,12,20)(2,6,10,14)(2,6,10,14,16)(2,6,10,14,16,18)(2,6,10,14,16,18,20)(2,6,10,14,16,20)(2,6,10,14,18)(2,6,10,14,18,20)(2,6,10,14,20)(2,6,10,16)(2,6,10,16,18)(2,6,10,16,18,20)(2,6,10,16,20)(2,6,10,18)(2,6,10,18,20)(2,6,10,20)(2,6,12)(2,6,12,14)(2,6,12,14,16)(2,6,12,14,16,18)(2,6,12,14,16,18,20)(2,6,12,14,16,20)(2,6,12,14,18)(2,6,12,14,18,20)(2,6,12,14,20)(2,6,12,16)(2,6,12,16,18)(2,6,12,16,18,20)(2,6,12,16,20)(2,6,12,18)(2,6,12,18,20)(2,6,12,20)(2,6,14)(2,6,14,16)(2,6,14,16,18)(2,6,14,16,18,20)(2,6,14,16,20)(2,6,14,18)(2,6,14,18,20)(2,6,14,20)(2,6,16)(2,6,16,18)(2,6,16,18,20)(2,6,16,20)(2,6,18)(2,6,18,20)(2,6,20)(2,8)(2,8,10)(2,8,10,12)(2,8,10,12,14)(2,8,10,12,14,16)(2,8,10,12,14,16,18)(2,8,10,12,14,16,18,20)(2,8,10,12,14,16,20)(2,8,10,12,14,18)(2,8,10,12,14,18,20)(2,8,10,12,14,20)(2,8,10,12,16)(2,8,10,12,16,18)(2,8,10,12,16,18,20)(2,8,10,12,16,20)(2,8,10,12,18)(2,8,10,12,18,20)(2,8,10,12,20)(2,8,10,14)(2,8,10,14,16)(2,8,10,14,16,18)(2,8,10,14,16,18,20)(2,8,10,14,16,20)(2,8,10,14,18)(2,8,10,14,18,20)(2,8,10,14,20)(2,8,10,16)(2,8,10,16,18)(2,8,10,16,18,20)(2,8,10,16,20)(2,8,10,18)(2,8,10,18,20)(2,8,10,20)(2,8,12)(2,8,12,14)(2,8,12,14,16)(2,8,12,14,16,18)(2,8,12,14,16,18,20)(2,8,12,14,16,20)(2,8,12,14,18)(2,8,12,14,18,20)(2,8,12,14,20)(2,8,12,16)(2,8,12,16,18)(2,8,12,16,18,20)(2,8,12,16,20)(2,8,12,18)(2,8,12,18,20)(2,8,12,20)(2,8,14)(2,8,14,16)(2,8,14,16,18)(2,8,14,16,18,20)(2,8,14,16,20)(2,8,14,18)(2,8,14,18,20)(2,8,14,20)(2,8,16)(2,8,16,18)(2,8,16,18,20)(2,8,16,20)(2,8,18)(2,8,18,20)(2,8,20)(2,10)(2,10,12)(2,10,12,14)(2,10,12,14,16)(2,10,12,14,16,18)(2,10,12,14,16,18,20)(2,10,12,14,16,20)(2,10,12,14,18)(2,10,12,14,18,20)(2,10,12,14,20)(2,10,12,16)(2,10,12,16,18)(2,10,12,16,18,20)(2,10,12,16,20)(2,10,12,18)(2,10,12,18,20)(2,10,12,20)(2,10,14)(2,10,14,16)(2,10,14,16,18)(2,10,14,16,18,20)(2,10,14,16,20)(2,10,14,18)(2,10,14,18,20)(2,10,14,20)(2,10,16)(2,10,16,18)(2,10,16,18,20)(2,10,16,20)(2,10,18)(2,10,18,20)(2,10,20)(2,12)(2,12,14)(2,12,14,16)(2,12,14,16,18)(2,12,14,16,18,20)(2,12,14,16,20)(2,12,14,18)(2,12,14,18,20)(2,12,14,20)(2,12,16)(2,12,16,18)(2,12,16,18,20)(2,12,16,20)(2,12,18)(2,12,18,20)(2,12,20)(2,14)(2,14,16)(2,14,16,18)(2,14,16,18,20)(2,14,16,20)(2,14,18)(2,14,18,20)(2,14,20)(2,16)(2,16,18)(2,16,18,20)(2,16,20)(2,18)(2,18,20)(2,20)(4)(4,6)(4,6,8)(4,6,8,10)(4,6,8,10,12)(4,6,8,10,12,14)(4,6,8,10,12,14,16)(4,6,8,10,12,14,16,18)(4,6,8,10,12,14,16,18,20)(4,6,8,10,12,14,16,20)(4,6,8,10,12,14,18)(4,6,8,10,12,14,18,20)(4,6,8,10,12,14,20)(4,6,8,10,12,16)(4,6,8,10,12,16,18)(4,6,8,10,12,16,18,20)(4,6,8,10,12,16,20)(4,6,8,10,12,18)(4,6,8,10,12,18,20)(4,6,8,10,12,20)(4,6,8,10,14)(4,6,8,10,14,16)(4,6,8,10,14,16,18)(4,6,8,10,14,16,18,20)(4,6,8,10,14,16,20)(4,6,8,10,14,18)(4,6,8,10,14,18,20)(4,6,8,10,14,20)(4,6,8,10,16)(4,6,8,10,16,18)(4,6,8,10,16,18,20)(4,6,8,10,16,20)(4,6,8,10,18)(4,6,8,10,18,20)(4,6,8,10,20)(4,6,8,12)(4,6,8,12,14)(4,6,8,12,14,16)(4,6,8,12,14,16,18)(4,6,8,12,14,16,18,20)(4,6,8,12,14,16,20)(4,6,8,12,14,18)(4,6,8,12,14,18,20)(4,6,8,12,14,20)(4,6,8,12,16)(4,6,8,12,16,18)(4,6,8,12,16,18,20)(4,6,8,12,16,20)(4,6,8,12,18)(4,6,8,12,18,20)(4,6,8,12,20)(4,6,8,14)(4,6,8,14,16)(4,6,8,14,16,18)(4,6,8,14,16,18,20)(4,6,8,14,16,20)(4,6,8,14,18)(4,6,8,14,18,20)(4,6,8,14,20)(4,6,8,16)(4,6,8,16,18)(4,6,8,16,18,20)(4,6,8,16,20)(4,6,8,18)(4,6,8,18,20)(4,6,8,20)(4,6,10)(4,6,10,12)(4,6,10,12,14)(4,6,10,12,14,16)(4,6,10,12,14,16,18)(4,6,10,12,14,16,18,20)(4,6,10,12,14,16,20)(4,6,10,12,14,18)(4,6,10,12,14,18,20)(4,6,10,12,14,20)(4,6,10,12,16)(4,6,10,12,16,18)(4,6,10,12,16,18,20)(4,6,10,12,16,20)(4,6,10,12,18)(4,6,10,12,18,20)(4,6,10,12,20)(4,6,10,14)(4,6,10,14,16)(4,6,10,14,16,18)(4,6,10,14,16,18,20)(4,6,10,14,16,20)(4,6,10,14,18)(4,6,10,14,18,20)(4,6,10,14,20)(4,6,10,16)(4,6,10,16,18)(4,6,10,16,18,20)(4,6,10,16,20)(4,6,10,18)(4,6,10,18,20)(4,6,10,20)(4,6,12)(4,6,12,14)(4,6,12,14,16)(4,6,12,14,16,18)(4,6,12,14,16,18,20)(4,6,12,14,16,20)(4,6,12,14,18)(4,6,12,14,18,20)(4,6,12,14,20)(4,6,12,16)(4,6,12,16,18)(4,6,12,16,18,20)(4,6,12,16,20)(4,6,12,18)(4,6,12,18,20)(4,6,12,20)(4,6,14)(4,6,14,16)(4,6,14,16,18)(4,6,14,16,18,20)(4,6,14,16,20)(4,6,14,18)(4,6,14,18,20)(4,6,14,20)(4,6,16)(4,6,16,18)(4,6,16,18,20)(4,6,16,20)(4,6,18)(4,6,18,20)(4,6,20)(4,8)(4,8,10)(4,8,10,12)(4,8,10,12,14)(4,8,10,12,14,16)(4,8,10,12,14,16,18)(4,8,10,12,14,16,18,20)(4,8,10,12,14,16,20)(4,8,10,12,14,18)(4,8,10,12,14,18,20)(4,8,10,12,14,20)(4,8,10,12,16)(4,8,10,12,16,18)(4,8,10,12,16,18,20)(4,8,10,12,16,20)(4,8,10,12,18)(4,8,10,12,18,20)(4,8,10,12,20)(4,8,10,14)(4,8,10,14,16)(4,8,10,14,16,18)(4,8,10,14,16,18,20)(4,8,10,14,16,20)(4,8,10,14,18)(4,8,10,14,18,20)(4,8,10,14,20)(4,8,10,16)(4,8,10,16,18)(4,8,10,16,18,20)(4,8,10,16,20)(4,8,10,18)(4,8,10,18,20)(4,8,10,20)(4,8,12)(4,8,12,14)(4,8,12,14,16)(4,8,12,14,16,18)(4,8,12,14,16,18,20)(4,8,12,14,16,20)(4,8,12,14,18)(4,8,12,14,18,20)(4,8,12,14,20)(4,8,12,16)(4,8,12,16,18)(4,8,12,16,18,20)(4,8,12,16,20)(4,8,12,18)(4,8,12,18,20)(4,8,12,20)(4,8,14)(4,8,14,16)(4,8,14,16,18)(4,8,14,16,18,20)(4,8,14,16,20)(4,8,14,18)(4,8,14,18,20)(4,8,14,20)(4,8,16)(4,8,16,18)(4,8,16,18,20)(4,8,16,20)(4,8,18)(4,8,18,20)(4,8,20)(4,10)(4,10,12)(4,10,12,14)(4,10,12,14,16)(4,10,12,14,16,18)(4,10,12,14,16,18,20)(4,10,12,14,16,20)(4,10,12,14,18)(4,10,12,14,18,20)(4,10,12,14,20)(4,10,12,16)(4,10,12,16,18)(4,10,12,16,18,20)(4,10,12,16,20)(4,10,12,18)(4,10,12,18,20)(4,10,12,20)(4,10,14)(4,10,14,16)(4,10,14,16,18)(4,10,14,16,18,20)(4,10,14,16,20)(4,10,14,18)(4,10,14,18,20)(4,10,14,20)(4,10,16)(4,10,16,18)(4,10,16,18,20)(4,10,16,20)(4,10,18)(4,10,18,20)(4,10,20)(4,12)(4,12,14)(4,12,14,16)(4,12,14,16,18)(4,12,14,16,18,20)(4,12,14,16,20)(4,12,14,18)(4,12,14,18,20)(4,12,14,20)(4,12,16)(4,12,16,18)(4,12,16,18,20)(4,12,16,20)(4,12,18)(4,12,18,20)(4,12,20)(4,14)(4,14,16)(4,14,16,18)(4,14,16,18,20)(4,14,16,20)(4,14,18)(4,14,18,20)(4,14,20)(4,16)(4,16,18)(4,16,18,20)(4,16,20)(4,18)(4,18,20)(4,20)(6)(6,8)(6,8,10)(6,8,10,12)(6,8,10,12,14)(6,8,10,12,14,16)(6,8,10,12,14,16,18)(6,8,10,12,14,16,18,20)(6,8,10,12,14,16,20)(6,8,10,12,14,18)(6,8,10,12,14,18,20)(6,8,10,12,14,20)(6,8,10,12,16)(6,8,10,12,16,18)(6,8,10,12,16,18,20)(6,8,10,12,16,20)(6,8,10,12,18)(6,8,10,12,18,20)(6,8,10,12,20)(6,8,10,14)(6,8,10,14,16)(6,8,10,14,16,18)(6,8,10,14,16,18,20)(6,8,10,14,16,20)(6,8,10,14,18)(6,8,10,14,18,20)(6,8,10,14,20)(6,8,10,16)(6,8,10,16,18)(6,8,10,16,18,20)(6,8,10,16,20)(6,8,10,18)(6,8,10,18,20)(6,8,10,20)(6,8,12)(6,8,12,14)(6,8,12,14,16)(6,8,12,14,16,18)(6,8,12,14,16,18,20)(6,8,12,14,16,20)(6,8,12,14,18)(6,8,12,14,18,20)(6,8,12,14,20)(6,8,12,16)(6,8,12,16,18)(6,8,12,16,18,20)(6,8,12,16,20)(6,8,12,18)(6,8,12,18,20)(6,8,12,20)(6,8,14)(6,8,14,16)(6,8,14,16,18)(6,8,14,16,18,20)(6,8,14,16,20)(6,8,14,18)(6,8,14,18,20)(6,8,14,20)(6,8,16)(6,8,16,18)(6,8,16,18,20)(6,8,16,20)(6,8,18)(6,8,18,20)(6,8,20)(6,10)(6,10,12)(6,10,12,14)(6,10,12,14,16)(6,10,12,14,16,18)(6,10,12,14,16,18,20)(6,10,12,14,16,20)(6,10,12,14,18)(6,10,12,14,18,20)(6,10,12,14,20)(6,10,12,16)(6,10,12,16,18)(6,10,12,16,18,20)(6,10,12,16,20)(6,10,12,18)(6,10,12,18,20)(6,10,12,20)(6,10,14)(6,10,14,16)(6,10,14,16,18)(6,10,14,16,18,20)(6,10,14,16,20)(6,10,14,18)(6,10,14,18,20)(6,10,14,20)(6,10,16)(6,10,16,18)(6,10,16,18,20)(6,10,16,20)(6,10,18)(6,10,18,20)(6,10,20)(6,12)(6,12,14)(6,12,14,16)(6,12,14,16,18)(6,12,14,16,18,20)(6,12,14,16,20)(6,12,14,18)(6,12,14,18,20)(6,12,14,20)(6,12,16)(6,12,16,18)(6,12,16,18,20)(6,12,16,20)(6,12,18)(6,12,18,20)(6,12,20)(6,14)(6,14,16)(6,14,16,18)(6,14,16,18,20)(6,14,16,20)(6,14,18)(6,14,18,20)(6,14,20)(6,16)(6,16,18)(6,16,18,20)(6,16,20)(6,18)(6,18,20)(6,20)(8)(8,10)(8,10,12)(8,10,12,14)(8,10,12,14,16)(8,10,12,14,16,18)(8,10,12,14,16,18,20)(8,10,12,14,16,20)(8,10,12,14,18)(8,10,12,14,18,20)(8,10,12,14,20)(8,10,12,16)(8,10,12,16,18)(8,10,12,16,18,20)(8,10,12,16,20)(8,10,12,18)(8,10,12,18,20)(8,10,12,20)(8,10,14)(8,10,14,16)(8,10,14,16,18)(8,10,14,16,18,20)(8,10,14,16,20)(8,10,14,18)(8,10,14,18,20)(8,10,14,20)(8,10,16)(8,10,16,18)(8,10,16,18,20)(8,10,16,20)(8,10,18)(8,10,18,20)(8,10,20)(8,12)(8,12,14)(8,12,14,16)(8,12,14,16,18)(8,12,14,16,18,20)(8,12,14,16,20)(8,12,14,18)(8,12,14,18,20)(8,12,14,20)(8,12,16)(8,12,16,18)(8,12,16,18,20)(8,12,16,20)(8,12,18)(8,12,18,20)(8,12,20)(8,14)(8,14,16)(8,14,16,18)(8,14,16,18,20)(8,14,16,20)(8,14,18)(8,14,18,20)(8,14,20)(8,16)(8,16,18)(8,16,18,20)(8,16,20)(8,18)(8,18,20)(8,20)(10)(10,12)(10,12,14)(10,12,14,16)(10,12,14,16,18)(10,12,14,16,18,20)(10,12,14,16,20)(10,12,14,18)(10,12,14,18,20)(10,12,14,20)(10,12,16)(10,12,16,18)(10,12,16,18,20)(10,12,16,20)(10,12,18)(10,12,18,20)(10,12,20)(10,14)(10,14,16)(10,14,16,18)(10,14,16,18,20)(10,14,16,20)(10,14,18)(10,14,18,20)(10,14,20)(10,16)(10,16,18)(10,16,18,20)(10,16,20)(10,18)(10,18,20)(10,20)(12)(12,14)(12,14,16)(12,14,16,18)(12,14,16,18,20)(12,14,16,20)(12,14,18)(12,14,18,20)(12,14,20)(12,16)(12,16,18)(12,16,18,20)(12,16,20)(12,18)(12,18,20)(12,20)(14)(14,16)(14,16,18)(14,16,18,20)(14,16,20)(14,18)(14,18,20)(14,20)(16)(16,18)(16,18,20)(16,20)(18)(18,20)(20)()
Since number of elements in the set can go upto 10^5 and hence the size of the set will go upto 2^(10^5) which is huge. You can just either print it or if you want to store it , store it in a file.
It is not possible, as you pointed out yourself power set contains pow(2, size) no of elements. You need to print the entire set that can only be done by generating the set using backtracking, there is nothing better. To find sum of all subsets of a given set is however a simpler problem. If the no of elements is n, then each element in the array occurs 2^(n-1) times in the power set. Pseudo code : int sum = 0; for(int i = 0;i < n;i++){ sum += ( set[i] * ( 1 << (n-1) ) ); //pow(2, n-1) == 1 << (n-1) } cout << sum << endl; You would need a Big Integer Library for larger values of n.