我需要澄清此question的答案,但我无法发表评论(代表人数不足),所以我问一个新问题。希望没事。
问题是这样的:
给定一个数组,您必须找到最大可能的两个相等和,您 可以排除元素。
即1,2,3,4,6给定数组,我们可以得到最多两个等于6 + 2 = 4 + 3 + 1
即4,10,18,22,我们可以得到两个相等的总和,即18 + 4 = 22
除了暴力破解之外,您还能采用什么方法解决此问题 强制查找所有计算并检查两个可能的相等和?
edit 1:数组元素的最大数目为N <= 50,每个元素可以为 最高1 <= K <= 1000
编辑2:元素总数之和不能大于1000。
批准的答案如下:
我建议使用DP解决此问题,而不是跟踪A,B( 两组的大小),而是跟踪A + B,A-B(总和 两组的差异)。
然后针对数组中的每个元素,尝试将其添加到A,B或 都不是。
跟踪和/差的优点是您只需要 跟踪每个差异的单个值,即最大 您所看到的总和值的差异。
我不了解的是:
如果这是子集和的问题,我可以用DP来解决,其记忆矩阵为(N x P),其中N是集合的大小,P是目标和...
但是我无法弄清楚我应该如何跟踪A + B,A-B(如已批准答案的作者所说)。记忆矩阵的维数应该是多少?以及如何帮助解决问题?
答案的作者很友好,可以提供一个代码示例,但是由于我不了解python(我知道java),所以我很难理解。
答案 0 :(得分:4)
我认为思考此解决方案与单个子集问题之间的关系可能会误导您。在这里,我们关心的是最大可实现的总和,此外,我们在遍历时需要区分两组不相交的数字。清楚地跟踪特定组合会太昂贵。
看看集合A和B之间的差异,我们可以说:
A - B = d
A = d + B
很显然,我们希望d = 0
时的总和最高。我们怎么知道那笔款项?是(A + B) / 2
!
对于动态程序中的过渡,我们想知道将当前元素放置在A,B还是都不放置中是更好的选择。可以这样实现:
e <- current element
d <- difference between A and B
(1) add e to A -> d + e
why?
A = d + B
(A + e) = d + e + B
(2) add e to B -> d - e
why?
A = d + B
A = d - e + (B + e)
(3) don't use e -> that's simply
what we already have stored for d
让我们看看Peter de Rivas的过渡代码:
# update a copy of our map, so
# we can reference previous values,
# while assigning new values
D2=D.copy()
# d is A - B
# s is A + B
for d,s in D.items():
# a new sum that includes element a
# we haven't decided if a
# will be in A or B
s2 = s + a
# d2 will take on each value here
# in turn, once d - a (adding a to B),
# and once d + a (adding a to A)
for d2 in [d-a, d+a]:
# The main transition:
# the two new differences,
# (d-a) and (d+a) as keys in
# our map get the highest sum
# seen so far, either (1) the
# new sum, s2, or (2) what we
# already stored (meaning `a`
# will be excluded here)
# so all three possibilities
# are covered.
D2[abs(d2)] = max(D2[abs(d2)], s2)
最后,我们存储了在d = 0时可见的最高A + B,其中A和B中的元素形成不交集。返回(A + B)/ 2。
答案 1 :(得分:1)
尝试此dp方法:它可以正常工作。
/*
*
i/p ::
1
5
1 2 3 4 6
o/p : 8
1
4
4 10 18 22
o/p : 22
1
4
4 118 22 3
o/p : 0
*/
import java.util.Scanner;
public class TwoPipesOfMaxEqualLength {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
int n = sc.nextInt();
int[] arr = new int[n + 1];
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
MaxLength(arr, n);
}
}
private static void MaxLength(int[] arr, int n) {
int dp[][] = new int[1005][1005];
int dp1[][] = new int[1005][1005];
// initialize dp with values as 0.
for (int i = 0; i <= 1000; i++) {
for (int j = 0; j <= 1000; j++)
dp[i][j] = 0;
}
// make (0,0) as 1.
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= 1000; j++) {
for (int k = 0; k <= 1000; k++) {
if (j >= arr[i]) {
if (dp[j - arr[i]][k] == 1) {
dp1[j][k] = 1;## Heading ##
}
}
if (k >= arr[i]) {
if (dp[j][k - arr[i]] == 1) {
dp1[j][k] = 1;
}
}
if (dp[j][k] == 1) {
dp1[j][k] = 1;
}
}
}
for (int j = 0; j <= 1000; j++) {
for (int k = 0; k <= 1000; k++) {
dp[j][k] = dp1[j][k];
dp1[j][k] = 0;
}
}
}
int ans = 0;
for (int i = 1; i <= 1000; i++) {
if (dp[i][i] == 1) {
ans = i;
}
}
System.out.println(ans);
}
}