给定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