仅使用set中的数字查找等于或大于给定目标的总和

时间:2014-03-04 18:30:47

标签: java algorithm

示例1:

商店出售啤酒,可用套餐每包6个和10个单位。客户输入26和算法回复26,因为26 = 10 + 10 + 6。

示例2:

销售香料,可用包装是0.6,1.5和3.目标值= 5.算法返回值5.1,因为它是最接近目标的数字,可以用包(3,1.5,0.6)实现。

我需要一个建议使用数字的Java方法。

Simmilar算法在Bin packing problem中描述,但它不适合我。 我尝试了它,当它返回给我的数字小于目标时,我再次使用增加的目标数量运行它。但是当包装数量巨大时效率不高。

我需要几乎相同的算法,但是使用相同或更大的最接近的数字。

类似的问题:Find if a number is a possible sum of two or more numbers in a given set - python

2 个答案:

答案 0 :(得分:4)

首先让我们将这个问题简化为整数而不是实数,否则我们将无法获得快速优化算法。例如,让我们将所有数字乘以100,然后将其四舍五入为下一个整数。所以说我们有项目大小 x 1 ,...,x n 和目标大小 Y 。我们希望最小化值

  

k 1 x 1 + ... + k n x n - Y

条件

  

(1) k i 是所有n≥i≥1

的非正整数

     

(2) k 1 x 1 + ... + k n x n - Y≥0

一个简单的算法就是提出一系列问题,比如

  1. 我们能实现 k 1 x 1 + ... + k n x n = Y + 0
  2. 我们能实现 k 1 x 1 + ... + k n x n = Y + 1
  3. 我们能实现 k 1 x 1 + ... + k n x n = Y + z
  4. 等。增加 z
  5. 直到我们得到答案“是”。所有这些问题都是Knapsack问题的实例,权重设置等于项目的值。好消息是,如果我们可以为 z 建立上限,我们可以一次解决所有这些问题。除非所有 x i 都大于 Y ,否则很容易证明存在z≤Y的解决方案>,在这种情况下,解决方案只是选择最小的 x i

    所以让我们使用pseudopolynomial dynamic programming approach来解决背包:让 f(i,j)为1,如果我们可以达到总项目大小 j i 项目(x 1 ,...,x i )。我们有复发

    f(0,0) = 1
    f(0,j) = 0   for all j > 0
    f(i,j) = f(i - 1, j) or f(i - 1, j - x_i) or f(i - 1, j - 2 * x_i) ...
    

    我们可以在 O(n * Y)时间和 O(Y)空间中解决此DP阵列。结果将是第一个j≥Y f(n,j)= 1

    有一些技术细节留给读者作为练习:

    • 如何在Java中实现此功能
    • 如果需要,如何重建解决方案。这可以使用DP阵列在 O(n)时间内完成(但是我们需要 O(n * Y)空间来记住整个事物。)

答案 1 :(得分:0)

你想解决整数规划问题min(ct)s.t。 ct> = T,c> = 0其中T是您的目标权重,c是非负整数向量,指定要购买的每个包的数量,t是指定每个包的权重的向量。您可以通过动态编程解决此问题,如另一个答案所指出的,或者,如果您的权重和目标权重太大,那么您可以使用通用整数编程求解器,这些求解器多年来经过高度优化,可在实践中提供良好的速度性能