📜  拔河

📅  最后修改于: 2021-05-04 13:58:30             🧑  作者: Mango

给定n个整数的集合,请将集合划分为n / 2个大小的两个子集,以使两个子集的总和之差尽可能小。如果n为偶数,则两个子集的大小必须严格为n / 2,如果n为奇数,则一个子集的大小必须为(n-1)/ 2,其他子集的大小必须为(n + 1)/ 2 。

例如,设给定的集合为{3,4,5,-3,100,1,89,54,23,20},集合的大小为10。该集合的输出应为{4,100,1, 23,20}和{3,5,-3,89,54}。两个输出子集的大小均为5,并且两个子集中的元素之和相同(148和148)。
让我们考虑另一个例子,其中n是奇数。设给定的集合为{23,45,-34,12,0,98,-99,4,189,-1,4}。输出子集应为{45,-34、12、98,-1}和{23、0,-99、4、189、4}。两个子集中的元素之和分别为120和121。

以下解决方案尝试使用每个可能的一半大小的子集。如果形成一半大小的一个子集,则其余元素形成另一个子集。我们将当前集合初始化为空,然后一一构建。每个元素都有两种可能性,要么是当前元素的一部分,要么是其余元素(其他子集)的一部分。我们考虑每个元素的两种可能性。当当前集合的大小变为n / 2时,我们检查此解决方案是否比目前可用的最佳解决方案好。如果是这样,那么我们将更新最佳解决方案。

以下是“拔河”问题的实现。它打印所需的数组。

C++
#include 
using namespace std;
  
// function that tries every possible solution by calling itself recursively
void 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


Java
// Java program for Tug of war
import java.util.*;
import java.lang.*;
import java.io.*;
  
class TugOfWar
{
    public int min_diff;
      
    // function that tries every possible solution
    // by calling itself recursively
    void TOWUtil(int arr[], int n, boolean curr_elements[],
               int no_of_selected_elements, boolean soln[],
               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, 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 (Math.abs(sum / 2 - curr_sum) <
                                  min_diff)
            {
                min_diff = Math.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, 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 arr
    void tugOfWar(int arr[])
    {
        int n = arr.length; 
  
        // the boolean array that contains the 
        // inclusion and exclusion of an element
        // in current set. The number excluded
        // automatically form the other set
        boolean[] curr_elements = new boolean[n];
          
        // The inclusion/exclusion array for 
        // final solution
        boolean[] soln = new boolean[n];
  
        min_diff = Integer.MAX_VALUE;
  
        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, sum, 0, 0);
  
        // Print the solution
        System.out.print("The first subset is: ");
        for (int i = 0; i < n; i++)
        {
            if (soln[i] == true)
                System.out.print(arr[i] + " ");
        }
        System.out.print("\nThe second subset is: ");
        for (int i = 0; i < n; i++)
        {
            if (soln[i] == false)
                System.out.print(arr[i] + " ");
        }
    }
      
    // Driver program to test above functions
    public static void main (String[] args) 
    {
        int arr[] = {23, 45, -34, 12, 0, 98,
                     -99, 4, 189, -1, 4};
        TugOfWar a = new TugOfWar();
        a.tugOfWar(arr);
    }
}
  
// This code is contributed by Chhavi


Python3
# Python3 program for above approach
  
# function that tries every possible 
# solution by calling itself recursively 
def TOWUtil(arr, n, curr_elements, no_of_selected_elements, 
            soln, min_diff, Sum, curr_sum, 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 ((int(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 += 1
    curr_sum = curr_sum + arr[curr_position] 
    curr_elements[curr_position] = True
  
    # checks if a solution is formed 
    if (no_of_selected_elements == int(n / 2)):
          
        # checks if the solution formed is better 
        # than the best solution so far 
        if (abs(int(Sum / 2) - curr_sum) < min_diff[0]):
            min_diff[0] = abs(int(Sum / 2) - curr_sum)
            for i in range(n):
                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 arr 
def tugOfWar(arr, n):
      
    # the boolean array that contains the 
    # inclusion and exclusion of an element 
    # in current set. The number excluded 
    # automatically form the other set 
    curr_elements = [None] * n 
  
    # The inclusion/exclusion array
    # for final solution 
    soln = [None] * n 
  
    min_diff = [999999999999] 
  
    Sum = 0
    for i in range(n):
        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 
    print("The first subset is: ")
    for i in range(n):
        if (soln[i] == True):
            print(arr[i], end = " ")
    print()
    print("The second subset is: ")
    for i in range(n):
        if (soln[i] == False):
            print(arr[i], end = " ")
  
# Driver Code
if __name__ == '__main__':
  
    arr = [23, 45, -34, 12, 0, 98, 
               -99, 4, 189, -1, 4] 
    n = len(arr) 
    tugOfWar(arr, n)
  
# This code is contributed by PranchalK


C#
// C# program for Tug of war 
using System;
  
class GFG 
{ 
    public int min_diff; 
      
    // function that tries every possible solution 
    // by calling itself recursively 
    void TOWUtil(int []arr, int n, Boolean []curr_elements, 
                 int no_of_selected_elements, Boolean []soln, 
                 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, 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 (Math.Abs(sum / 2 - curr_sum) < 
                                   min_diff) 
            { 
                min_diff = Math.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, 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 arr 
    void tugOfWar(int []arr) 
    { 
        int n = arr.Length; 
  
        // the boolean array that contains the 
        // inclusion and exclusion of an element 
        // in current set. The number excluded 
        // automatically form the other set 
        Boolean[] curr_elements = new Boolean[n]; 
          
        // The inclusion/exclusion array for 
        // final solution 
        Boolean[] soln = new Boolean[n]; 
  
        min_diff = int.MaxValue; 
  
        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, sum, 0, 0); 
  
        // Print the solution 
        Console.Write("The first subset is: "); 
        for (int i = 0; i < n; i++) 
        { 
            if (soln[i] == true) 
                Console.Write(arr[i] + " "); 
        } 
        Console.Write("\nThe second subset is: "); 
        for (int i = 0; i < n; i++) 
        { 
            if (soln[i] == false) 
                Console.Write(arr[i] + " "); 
        } 
    } 
      
    // Driver Code
    public static void Main (String[] args) 
    { 
        int []arr = {23, 45, -34, 12, 0, 98, 
                    -99, 4, 189, -1, 4}; 
        GFG a = new GFG(); 
        a.tugOfWar(arr); 
    } 
} 
  
// This code is contributed by 29AjayKumar


PHP
 
                             ($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 == intval($n / 2)) 
    { 
        // checks if the solution formed is
        // better than the best solution so far 
        if (abs(intval($sum / 2) - 
                       $curr_sum) < $min_diff) 
        { 
            $min_diff = abs(intval($sum / 2) - 
                                   $curr_sum); 
            for ($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 arr 
function tugOfWar(&$arr, $n) 
{ 
    // the boolean array that contains the 
    // inclusion and exclusion of an element 
    // in current set. The number excluded
    // automatically form the other set 
    $curr_elements = array_fill(0, $n, 0);
  
    // The inclusion/exclusion array
    // for final solution 
    $soln = array_fill(0, $n, 0);
  
    $min_diff = PHP_INT_MAX; 
  
    $sum = 0; 
    for ($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 
    echo "The first subset is: "; 
    for ($i = 0; $i < $n; $i++) 
    { 
        if ($soln[$i] == true) 
            echo $arr[$i] . " "; 
    } 
    echo "\nThe second subset is: "; 
    for ($i = 0; $i < $n; $i++) 
    { 
        if ($soln[$i] == false) 
            echo $arr[$i] . " "; 
    } 
} 
  
// Driver Code
$arr = array(23, 45, -34, 12, 0, 98,
            -99, 4, 189, -1, 4); 
$n = count($arr); 
tugOfWar($arr, $n); 
  
// This code is contributed
// by rathbhupendra
?>


输出:

The first subset is: 45 -34 12 98 -1
The second subset is: 23 0 -99 4 189 4