数字乘数的总和大于或等于目标,优化

时间:2014-01-31 05:21:59

标签: algorithm vector multiplication subset-sum

给出一个等式

类似2(p 1 )+ 3(p 2 )+ 7(p 3 )> = 257

我需要找到p 1 ,p 2 ,p 3 的所有可能组合 这样的上述陈述是正确的,并且所得的总和(等式的左边)是最小的,其中所有x n 都是已知的。

我尝试查找一般情况下的算法,例如

(x 1 )(p 1 )+(x 2 )(p 2 )+( x 3 )(p 4 )+ ... +(x n )(p n )> =目标

我遇到了背包问题和Subset-Sum算法解决方案,但它们并不完全像这个问题。

我之前尝试过使用Python 3.x中的算法,该算法具有p n 的下限值,但它仍然以O(荒谬)时间复杂度运行。

显然,这里的所有数字都是自然数,否则会有无限的解。

2 个答案:

答案 0 :(得分:1)

也许给出的例子只是一个玩具案例。

如果没有,穷举搜索是非常可行的:最小总和受259(组合0,0,37)的限制,并且在这个界限下有不到50万个组合。

另外,如果设置两个变量,比如说p2和p3,那么3(p2)+7(p3)&lt; 257,找到最小的p1是很容易的,使得2(p1)+ 3(p2)+ 7(p3)> = 257.你将只需要尝试3200(p2,p3)组合。< / p>

答案 1 :(得分:1)

我可以看到两种可能的方法,取决于Pi是否必须> = 0.Pi> = 0的情况更明智,所以我会先考虑它。

将其视为动态编程,您可以沿着等式从左向右工作。查看注释中较大的等式,首先创建一个来自p0:0,5,10,15 ... 190384760的贡献列表,并在它们旁边生成它们的p0的值:0,1,2, ...... 190384760/5。

现在使用此表通过组合前两个来计算5p0 + 7p1的值:0,5,7,10,12,14 ....并保持生成它们所需的p1值。 / p>

从右到左工作,最终会得到一个最大值超过190384755的表,可以通过p0..p8的正整数组合创建。您显然只关心最大的一个&gt; = 190384755.考虑p8贡献的所有可能值,从190384755中减去这些值,并在表格中查找p0..p7以查看哪些是可能的。这给出了所有可能的p8值,并且对于每个值,您可以递归地重复该过程以打印出p7的所有可能值,依此类推重复递归以提供产生最低值的p0..p8的所有值这与用于子集和的伪多项式算法非常相似。

如果Pi可以&lt; 0,那么可实现的值都是Pi的gcd的倍数,这很可能是所有整数,并且存在无限数量的解决方案。如果这真的是你想要的,你可以先阅读http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm