RainX_69

Minimum Subset sum difference problem with Subset partitioning | meet in the middle | MUST DO | OA

May 13th, 2023
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.32 KB | Source Code | 0 0
  1. https://practice.geeksforgeeks.org/problems/partition-a-set-into-two-subsets-such-that-the-difference-of-subset-sums-is-minimum-set-2/1
  2. article (author: Abhijit)- https://www.geeksforgeeks.org/minimum-subset-sum-difference-problem-with-subset-partitioning/
  3.  
  4.  
  5. Given a set of N integers with up to 40 elements, the task is to partition the set into two subsets of equal size (or the closest possible), such that the difference between the sums of the subsets is minimized. If the size of the set is odd, one subset will have one more element than the other. If the size is even, both subsets will have the same size. After finding the minimum difference, output the subsets.
  6.  
  7. Examples:
  8.  
  9. Input: arr[] = {45, 34, 4, 12, 5, 2}
  10. Output: Min Difference 0 Subset 1 : {34, 12,  5} Subset 2 : {45,  4,  2}                        
  11. Explanation: The above generated two subsets have sum
  12. ∑ Subset 1 : 34+12+5 =  51
  13. ∑ Subset 2 : 45+4+2 =  51
  14. The minimum difference is abs( ∑ S1 – ∑ S2 ) = 0, which is the minimum difference possible.
  15.  
  16. Input: arr[] = {3, 34, 4, 12, 5, 2 }
  17. Output: Min Difference 18 Subset 1 : {3  34  2} Subset 2 : {4  12  5 }                
  18. Explanation: The above generated two subsets have sum
  19. ∑ Subset 1 : 3+34+2 =  39
  20. ∑ Subset 2 : 4+12+5 =  21
  21. The minimum difference is abs( ∑ S1 – ∑ S2 ) = 18, which is the minimum difference possible.
  22.  
  23. ---------------------------------------------------------------------------------------------------------------------------------------
  24.  
  25. #include <bits/stdc++.h>
  26. using namespace std;
  27.  
  28. struct Info {
  29.     int sum;
  30.     vector<int> indices;
  31. };
  32.  
  33. static bool cmp(Info& p1, Info& p2)
  34. {
  35.     return p1.sum < p2.sum;
  36. }
  37.  
  38. void generate(vector<int>& arr, int curr, int n, int sum,
  39.             vector<vector<Info> >& store,
  40.             vector<int> build)
  41. {
  42.     if (curr == n) {
  43.         int sz = build.size();
  44.         store[sz].push_back({ sum, build });
  45.         return;
  46.     }
  47.     build.push_back(curr);
  48.     generate(arr, curr + 1, n, sum + arr[curr], store,
  49.             build);
  50.     build.pop_back();
  51.     generate(arr, curr + 1, n, sum, store, build);
  52. }
  53.  
  54. int BINRY_SRCH(vector<Info>& arr, int target)
  55. {
  56.  
  57.     // Lower bound
  58.     int res = -1;
  59.     int low = 0;
  60.     int high = arr.size() - 1;
  61.     while (low <= high) {
  62.         int mid = (low + high) / 2;
  63.         if (arr[mid].sum >= target) {
  64.             res = mid;
  65.             high = mid - 1;
  66.         }
  67.         else {
  68.             low = mid + 1;
  69.         }
  70.     }
  71.     return res;
  72. }
  73.  
  74. vector<vector<int> > minDifference(vector<int>& arr, int n)
  75. {
  76.     int extra = (n % 2 != 0);
  77.  
  78.     vector<vector<Info> > part1(n / 2 + 1 + extra);
  79.     vector<vector<Info> > part2(n / 2 + 1);
  80.  
  81.     generate(arr, 0, n / 2 + extra, 0, part1, {});
  82.     generate(arr, n / 2 + extra, n, 0, part2, {});
  83.  
  84.     for (auto& vec : part2) {
  85.  
  86.         // Sorting part2 to prepare
  87.         // for binary search
  88.         sort(vec.begin(), vec.end(), cmp);
  89.     }
  90.  
  91.     vector<vector<int> > res(2);
  92.  
  93.     int diff = INT_MAX;
  94.     int TS = accumulate(arr.begin(), arr.end(), 0);
  95.  
  96.     // Making subset1
  97.     for (int ele = 1; ele <= n / 2 + extra; ele++) {
  98.  
  99.         // Taking only ele
  100.         // elements from part1
  101.         vector<Info> P1 = part1[ele];
  102.  
  103.         // Taking rest of the elements
  104.         // for subset1 from part2
  105.         vector<Info> P2 = part2[n / 2 + extra - ele];
  106.  
  107.         // Iterating for each sum in P1
  108.         for (auto x : P1) {
  109.  
  110.             // P1sum -> subset1 sum
  111.             // P2sum -> subset2 sum
  112.  
  113.             // For absolute minimisation,
  114.             // each subset should be having
  115.             // sum close to TS/2. If we
  116.             // take x sum from Part1, then
  117.             // remaining sum TS/2-x should
  118.             // be taken from part2. We
  119.             // want to get a sum closer to
  120.             // this target. For this, do
  121.             // binary search.
  122.             int index = BINRY_SRCH(P2, TS / 2 - x.sum);
  123.             if (index != -1) {
  124.                 int subset1_Sum = x.sum + P2[index].sum;
  125.                 int subset2_Sum = TS - subset1_Sum;
  126.  
  127.                 if (abs(subset1_Sum - subset2_Sum) < diff) {
  128.                     diff = abs(subset1_Sum - subset2_Sum);
  129.  
  130.                     // Storing the subset
  131.                     vector<int> subset1 = x.indices;
  132.                     for (auto c : P2[index].indices) {
  133.                         subset1.push_back(c);
  134.                     }
  135.                     res[0] = subset1;
  136.                 }
  137.             }
  138.  
  139.             if (index > 0) {
  140.                 index--;
  141.                 int subset1_Sum = x.sum + P2[index].sum;
  142.                 int subset2_Sum = TS - subset1_Sum;
  143.  
  144.                 if (abs(subset1_Sum - subset2_Sum) < diff) {
  145.                     diff = abs(subset1_Sum - subset2_Sum);
  146.  
  147.                     // Storing the subset
  148.                     vector<int> subset1 = x.indices;
  149.                     for (auto c : P2[index].indices) {
  150.                         subset1.push_back(c);
  151.                     }
  152.                     res[0] = subset1;
  153.                 }
  154.             }
  155.         }
  156.     }
  157.  
  158.     // Find subset2 after ignoring elements
  159.     // of subset1 in arr
  160.  
  161.     vector<bool> vis(n, false);
  162.  
  163.     for (int i = 0; i < res[0].size(); i++) {
  164.         vis[res[0][i]] = true;
  165.         res[0][i] = arr[res[0][i]];
  166.     }
  167.  
  168.     vector<int> subset2;
  169.     for (int i = 0; i < n; i++) {
  170.         if (vis[i] == false) {
  171.             subset2.push_back(arr[i]);
  172.         }
  173.     }
  174.     res[1] = subset2;
  175.  
  176.     cout << "Min Difference " << diff << endl;
  177.  
  178.     return res;
  179. }
  180.  
  181. void PRINT(vector<vector<int> >& subsets)
  182. {
  183.     cout << "Subset 1 : ";
  184.     for (auto x : subsets[0]) {
  185.         cout << x << " ";
  186.     }
  187.     cout << endl
  188.         << "Subset 2 : ";
  189.     for (auto x : subsets[1]) {
  190.         cout << x << " ";
  191.     }
  192. }
  193.  
  194. int main()
  195. {
  196.     vector<int> arr;
  197.     vector<vector<int> > res;
  198.  
  199.     arr = {45, 34, 4, 12, 5, 2 };
  200.     res = minDifference(arr, arr.size());
  201.     PRINT(res);
  202.     return 0;
  203. }
  204.  
  205.  
  206. O( 2^(n/2)  * log(2^(n/2)) *  n/2 ),  O(2^(n/2)) is for generating two subsets, O(log(2^(n/2))) for binary searching for each element of part1 in part2, hence the extra n/2 factor.
  207.  
  208.  
Advertisement
Add Comment
Please, Sign In to add comment