#include <bits/stdc++.h> using namespace std; struct Info { int sum; vector<int> indices; }; static bool cmp(Info& p1, Info& p2) { return p1.sum < p2.sum; } void generate(vector<int>& arr, int curr, int n, int sum, vector<vector<Info> >& store, vector<int> build) { if (curr == n) { int sz = build.size(); store[sz].push_back({ sum, build }); return; } build.push_back(curr); generate(arr, curr + 1, n, sum + arr[curr], store, build); build.pop_back(); generate(arr, curr + 1, n, sum, store, build); } int BINRY_SRCH(vector<Info>& arr, int target) { // Lower bound int res = -1; int low = 0; int high = arr.size() - 1; while (low <= high) { int mid = (low + high) / 2; if (arr[mid].sum >= target) { res = mid; high = mid - 1; } else { low = mid + 1; } } return res; } vector<vector<int> > minDifference(vector<int>& arr, int n) { int extra = (n % 2 != 0); vector<vector<Info> > part1(n / 2 + 1 + extra); vector<vector<Info> > part2(n / 2 + 1); generate(arr, 0, n / 2 + extra, 0, part1, {}); generate(arr, n / 2 + extra, n, 0, part2, {}); for (auto& vec : part2) { // Sorting part2 to prepare // for binary search sort(vec.begin(), vec.end(), cmp); } vector<vector<int> > res(2); int diff = INT_MAX; int TS = accumulate(arr.begin(), arr.end(), 0); // Making subset1 for (int ele = 1; ele <= n / 2 + extra; ele++) { // Taking only ele // elements from part1 vector<Info> P1 = part1[ele]; // Taking rest of the elements // for subset1 from part2 vector<Info> P2 = part2[n / 2 + extra - ele]; // Iterating for each sum in P1 for (auto x : P1) { // P1sum -> subset1 sum // P2sum -> subset2 sum // For absolute minimisation, // each subset should be having // sum close to TS/2. If we // take x sum from Part1, then // remaining sum TS/2-x should // be taken from part2. We // want to get a sum closer to // this target. For this, do // binary search. int index = BINRY_SRCH(P2, TS / 2 - x.sum); if (index != -1) { int subset1_Sum = x.sum + P2[index].sum; int subset2_Sum = TS - subset1_Sum; if (abs(subset1_Sum - subset2_Sum) < diff) { diff = abs(subset1_Sum - subset2_Sum); // Storing the subset vector<int> subset1 = x.indices; for (auto c : P2[index].indices) { subset1.push_back(c); } res[0] = subset1; } } if (index > 0) { index--; int subset1_Sum = x.sum + P2[index].sum; int subset2_Sum = TS - subset1_Sum; if (abs(subset1_Sum - subset2_Sum) < diff) { diff = abs(subset1_Sum - subset2_Sum); // Storing the subset vector<int> subset1 = x.indices; for (auto c : P2[index].indices) { subset1.push_back(c); } res[0] = subset1; } } } } // Find subset2 after ignoring elements // of subset1 in arr vector<bool> vis(n, false); for (int i = 0; i < res[0].size(); i++) { vis[res[0][i]] = true; res[0][i] = arr[res[0][i]]; } vector<int> subset2; for (int i = 0; i < n; i++) { if (vis[i] == false) { subset2.push_back(arr[i]); } } res[1] = subset2; cout << "Min Difference " << diff << endl; return res; } void PRINT(vector<vector<int> >& subsets) { cout << "Subset 1 : "; for (auto x : subsets[0]) { cout << x << " "; } cout << endl << "Subset 2 : "; for (auto x : subsets[1]) { cout << x << " "; } } // Drivers code int main() { vector<int> arr; vector<vector<int> > res; arr = {45, 34, 4, 12, 5, 2 }; res = minDifference(arr, arr.size()); PRINT(res); return 0; } // Author:- RainX (Abhijit Roy, NIT AGARTALA)