Problem:
1. there is an unordered positive integer array with the number of elements being 2n. The requirement is: how to split the array into two subarrays. The number of subarrays is not limited, and the sum of the two subarrays is the closest.
2. There is an unordered positive integer array with 2n elements. Requirement: how to divide the array into two arrays with n as the number of elements, and make the sum of the two subarrays closest to each other.
Ps: This is just my understanding of the solution to this problem. In fact, it still feels a bit awkward. If you have a better way of thinking, I 'd like to tell you, thank you.
1. solution:
We need to convert the question properly because the two subarrays and the closest judgment are not intuitive. We know that when the sum of a sub-array is half of the sum of the original array, the sum of the two sub-arrays is the closest. So the converted question is: select any number from the 2n number, which is as close as possible to the given value sum/2.
The problem is that any number is selected from the previous k number, and whether the sum of this number exists in dp [k] [s]. The reason why we put the sum of the selected numbers in the subscript instead of the value of dp [k] is that this approach does not meet the premise of Dynamic Planning-optimization principle, suppose we find that the optimal solution has k numbers (the sum of these k numbers is the closest to sum/2 ), however, the sum of the number of K-1 before the optimal solution in the sum of the number of K-1 may not be the closest to sum/2, that is, the sub-Problem of the optimal solution is not optimal, so it does not meet the optimization principle. Therefore, we need to store the value of dp [k] As a subscript, convert this optimal problem into a judgment problem, and use the progressive method with the idea of dynamic planning to solve it.
External stage: select the first k1 number, k1 = 1, 2... 2 * n.
Internal stage: select any number of k2 from the number of k1, k2 = 1, 2... k1.
Status: the sum of the k2 numbers is s, s = 1, 2... sum/2.
Decision-making: There are two types of decision-making: one is that the k2 number contains the k1 number, and the other is not the k1 number.
Dp [k] [s] indicates to take any number from the previous k number, and whether the sum of these numbers is s.
[Cpp]
# Include <iostream>
# Include <algorithm>
Using namespace std;
# Define maxn101
# Define maxsum100000
Int A [MAXN];
Bool dp [MAXN] [MAXSUM];
// Dp [k] [s] indicates to remove any number from the previous k number, and whether the sum of these numbers is s's obtaining Method
Int main ()
{
Int n, I, k1, k2, s, u;
Cin> n;
For (I = 1; I <= 2 * n; I ++)
Cin> A [I];
Int sum = 0;
For (I = 1; I <= 2 * n; I ++)
Sum + = A [I];
Memset (dp, 0, sizeof (dp ));
Dp [0] [0] = true;
// K1 indicates the k1 number, and k2 indicates the number of the selected number.
For (k1 = 1; k1 <= 2 * n; k1 ++) // external stage k1
{
For (k2 = k1; k2> = 1; k2 --) // In-stage k2
For (s = 1; s <= sum/2; s ++) // status s
{
// Dp [k1] [s] = dp [k1-1] [s];
// There are two decisions that contain or do not contain element k1
If (s> = A [k1] & dp [k2-1] [s-A [k1])
Dp [k2] [s] = true;
}
}
// The previous dp [k] [s] indicates taking any k number from the previous k number. After the following steps
// Indicates taking any number from the previous k count
For (k1 = 2; k1 <= 2 * n; k1 ++)
For (s = 1; s <= sum/2; s ++)
If (dp [k1-1] [s]) dp [k1] [s] = true;
// Determine sum/2 and
For (s = sum/2; s> = 1 &&! Dp [2 * n] [s]; s --);
Printf ("the differece between two sub array is % d \ n", sum-2 * s );
}
2. Solution: www.2cto.com
However, this question also adds a restriction that the number of selected objects must be n, which limits the value range of k2 in the stage, the meaning of dp [k] [s] also changes. Here, dp [k] [s] indicates whether the number of any k that cannot exceed n is obtained from the previous k number, and whether the sum of these numbers exists.
[Cpp]
# Include <iostream>
# Include <algorithm>
Using namespace std;
# Define maxn101
# Define maxsum100000
Int A [MAXN];
Bool dp [MAXN] [MAXSUM];
// The question can be converted to selecting n numbers from the 2n number, which is as close as possible to the given value sum/2.
Int main ()
{
Int n, I, k1, k2, s, u;
Cin> n;
For (I = 1; I <= 2 * n; I ++)
Cin> A [I];
Int sum = 0;
For (I = 1; I <= 2 * n; I ++)
Sum + = A [I];
Memset (dp, 0, sizeof (dp ));
Dp [0] [0] = true;
// For dp [k] [s], u-level decision-making is required because the selection of phase k is limited by decision-making,
// Here, the decision-making options cannot be repeated, but the stages can be repeated, especially
For (k1 = 1; k1 <= 2 * n; k1 ++) // external stage k1
For (k2 = min (k1, n); k2> = 1; k2 --) // stage k2
For (s = 1; s <= sum/2; s ++) // status s
// There are two decisions that contain or do not contain element k1
If (s> = A [k1] & dp [k2-1] [s-A [k1])
Dp [k2] [s] = true;
// Determine sum/2 and
For (s = sum/2; s> = 1 &&! Dp [n] [s]; s --);
Printf ("the differece between two sub array is % d \ n", sum-2 * s );
}
Author: linyunzju