Tug of War | GeeksforGeeks
Given a set of n integers, divide the set in two subsets of n/2 sizes each such that the difference of the sum of two subsets is as minimum as possible. If n is even, then sizes of two subsets must be strictly n/2 and if n is odd, then size of one subset must be (n-1)/2 and size of other subset must be (n+1)/2.
The following solution tries every possible subset of half size. If one subset of half size is formed, the remaining elements form the other subset. We initialize current set as empty and one by one build it. There are two possibilities for every element, either it is part of current set, or it is part of the remaining elements (other subset). We consider both possibilities for every element. When the size of current set becomes n/2, we check whether this solutions is better than the best solution available so far. If it is, then we update the best solution.
http://codefordummies.blogspot.com/2013/10/backtracking-tug-of-war.html
It's not good to always compute selected size and diff every time.
// 1. in each iteration, either add or remove the current element from the selected array // 2. check if we have already selected the requried number of elements, in that case update solution // 3. check if have already reached the end of the array, in that case, simply return protected static void solve(int currentIndex) { // get size of selected int selectedSize = 0; for (int i = 0; i < n; i++) if (selected[i]) selectedSize++; if (selectedSize == n / 2) { // check if diff < minDiff, update solution int diff = getDiff(); if (diff < minDiff) { minDiff = diff; updateSolution(); } } // check if currentIndex == n and return if (currentIndex >= n) return; // add curindex to selected selected[currentIndex] = true; solve(currentIndex + 1); // remove curindex from selected selected[currentIndex] = false; solve(currentIndex + 1); }
protected static int getDiff() { int leftSum = 0; int rightSum = 0; for (int i = 0; i < n; i++) { if (selected[i]) leftSum += a[i]; else rightSum += a[i]; } return Math.abs(rightSum - leftSum); }
Read full article from Tug of War | GeeksforGeeks
Given a set of n integers, divide the set in two subsets of n/2 sizes each such that the difference of the sum of two subsets is as minimum as possible. If n is even, then sizes of two subsets must be strictly n/2 and if n is odd, then size of one subset must be (n-1)/2 and size of other subset must be (n+1)/2.
The following solution tries every possible subset of half size. If one subset of half size is formed, the remaining elements form the other subset. We initialize current set as empty and one by one build it. There are two possibilities for every element, either it is part of current set, or it is part of the remaining elements (other subset). We consider both possibilities for every element. When the size of current set becomes n/2, we check whether this solutions is better than the best solution available so far. If it is, then we update the best solution.
// function that tries every possible solution by calling itself recursivelyvoid TOWUtil(int* arr, int n, bool* curr_elements, int no_of_selected_elements, bool* soln, int* min_diff, int sum, int curr_sum, int curr_position){ // checks whether the it is going out of bound if (curr_position == n) return; // checks that the numbers of elements left are not less than the // number of elements required to form the solution if ((n/2 - no_of_selected_elements) > (n - curr_position)) return; // consider the cases when current element is not included in the solution TOWUtil(arr, n, curr_elements, no_of_selected_elements, soln, min_diff, sum, curr_sum, curr_position+1); // add the current element to the solution no_of_selected_elements++; curr_sum = curr_sum + arr[curr_position]; curr_elements[curr_position] = true; // checks if a solution is formed if (no_of_selected_elements == n/2) { // checks if the solution formed is better than the best solution so far if (abs(sum/2 - curr_sum) < *min_diff) { *min_diff = abs(sum/2 - curr_sum); for (int i = 0; i<n; i++) soln[i] = curr_elements[i]; } } else { // consider the cases where current element is included in the solution TOWUtil(arr, n, curr_elements, no_of_selected_elements, soln, min_diff, sum, curr_sum, curr_position+1); } // removes current element before returning to the caller of this function curr_elements[curr_position] = false;}// main function that generate an arrvoid tugOfWar(int *arr, int n){ // the boolen array that contains the inclusion and exclusion of an element // in current set. The number excluded automatically form the other set bool* curr_elements = new bool[n]; // The inclusion/exclusion array for final solution bool* soln = new bool[n]; int min_diff = INT_MAX; int sum = 0; for (int i=0; i<n; i++) { sum += arr[i]; curr_elements[i] = soln[i] = false; } // Find the solution using recursive function TOWUtil() TOWUtil(arr, n, curr_elements, 0, soln, &min_diff, sum, 0, 0); // Print the solution cout << "The first subset is: "; for (int i=0; i<n; i++) { if (soln[i] == true) cout << arr[i] << " "; } cout << "\nThe second subset is: "; for (int i=0; i<n; i++) { if (soln[i] == false) cout << arr[i] << " "; }}http://codefordummies.blogspot.com/2013/10/backtracking-tug-of-war.html
It's not good to always compute selected size and diff every time.
// 1. in each iteration, either add or remove the current element from the selected array // 2. check if we have already selected the requried number of elements, in that case update solution // 3. check if have already reached the end of the array, in that case, simply return protected static void solve(int currentIndex) { // get size of selected int selectedSize = 0; for (int i = 0; i < n; i++) if (selected[i]) selectedSize++; if (selectedSize == n / 2) { // check if diff < minDiff, update solution int diff = getDiff(); if (diff < minDiff) { minDiff = diff; updateSolution(); } } // check if currentIndex == n and return if (currentIndex >= n) return; // add curindex to selected selected[currentIndex] = true; solve(currentIndex + 1); // remove curindex from selected selected[currentIndex] = false; solve(currentIndex + 1); }
protected static int getDiff() { int leftSum = 0; int rightSum = 0; for (int i = 0; i < n; i++) { if (selected[i]) leftSum += a[i]; else rightSum += a[i]; } return Math.abs(rightSum - leftSum); }
Read full article from Tug of War | GeeksforGeeks