其他人说的是真的:
这个问题是NP完全的。一个简单的减少是通常的子集和。您可以通过注意仅当 A 的非空子集 (-B) 的总和为零时,才可以通过注意 A 的子集与 B 的子集(不是都为空)相加来证明这一点。
这个问题只是弱 NP 完全问题,因为它在所涉及的数字的大小上是多项式的,但被推测为对数是指数的。这意味着这个问题比绰号“NP-complete”可能暗示的要容易。
您应该使用动态编程。
那么我对这个讨论有什么贡献呢?好吧,代码(在 Perl 中):
@a = qw(4 5 9 10 1);
@b = qw(21 7 -4 180);
%a = sums( @a );
%b = sums( @b );
for $m ( keys %a ) {
next unless exists $b{$m};
next if $m == 0 and (@{$a{0}} == 0 or @{$b{0}} == 0);
print "sum(@{$a{$m}}) = sum(@{$b{$m}})\n";
}
sub sums {
my( @a ) = @_;
my( $a, %a, %b );
%a = ( 0 => [] );
while( @a ) {
%b = %a;
$a = shift @a;
for my $m ( keys %a ) {
$b{$m+$a} = [@{$a{$m}},$a];
}
%a = %b;
}
return %a;
}
它打印
sum(4 5 9 10) = sum(21 7)
sum(4 9 10 1) = sum(21 7 -4)
因此,值得注意的是,有不止一种解决方案可以解决您的原始问题!
编辑:用户 itzy 正确地指出这个解决方案是错误的,更糟糕的是,在多个方面!!对此我感到非常抱歉,我希望在上面的新代码中解决了这些问题。尽管如此,仍然存在一个问题,即对于任何特定的子集和,它只打印出一种可能的解决方案。与之前的问题不同,这些问题是直接错误,我将其归类为故意限制。祝你好运并提防错误!