给定数字和间隔集的分布算法

时间:2009-08-15 06:01:06

标签: algorithm numbers distribution

我正在寻找一种算法,可以解决下面描述的问题。 我已经编写了一个算法(我认为它过于专业化,无法发布),尽可能地优化,但在更大的数字集上它仍然太慢(因为成本呈指数增长)。在合适的计算机上,解决方案的时间不应超过5秒。

你会得到一组数字,例如:

M = {1,1,1,2,2,5,5,5,10,10,10,10,20,50,50,50, ...... ,10000,10000,20000,20000}

不必具有特殊结构(尽管它们在这里)。

您将获得一组“目标点”,也包括数字,例如:

P = {670,2010,5600,10510,15000}

目标是,从M中取出最少数量的数字,当您按照确定的顺序添加数字时,您将获得中间结果关闭 P中的所有点都可以使用。您只能使用M中的每个数字。

在我们的例子中,可能的解决方案是(虽然我不知道它是否是最好的):

Y =(500,100, 50 ; 1000,200,200; 2000,1000,500; 5000; 2000,2000)

正如您所看到的,两种标准至少关闭进行某种权衡。这就是我当前算法使用评分来找到“最佳”解决方案的原因。

以下是目前的工作原理:

  1. 排序M,排序P,升序
  2. 删除数字太小而无法相关更改分数或数字太大
  3. 递归:
  4. 将P中的下一个点作为当前“目标”,加上减去例如10%
  5. 从M中添加下一个数字,如果M
  6. 将其删除
  7. 当靠近目标点时,转到4.如果在结束点,计算当前分布的分数并可能记住它
  8. 其他转到5
  9. 从尝试号码返回时,请使用下一个更高的号码
  10. 它从不尝试两个相同的数字,只尝试升序,例如:

    • 100,100,100,50,50,20,10
    • 100,100,100,50,50,20,20
    • 100,100,100,50,50,50,10
    • 100,100,100,50,50,50,20
    • 100,100,100,50,50,50,50
    • 100,100,100,100
    • 100,100,100,100,10
    • 100,100,100,100,20
    • ...

    每个数字大约有5个,并删除了许多较小的数字,算法非常快,并找到了一个很好的解决方案。但是当我添加更多数字或特别是包含更小的数字时,运行时从100ms上升到无穷大。

    你能给我一个提示,如何处理这个问题?文献中是否有类似的算法可以处理问题或其中的一部分?

3 个答案:

答案 0 :(得分:0)

这有点类似于Knapsack Problem

答案 1 :(得分:0)

Lemme尝试,它可能不是最好的,但应该很好地工作。我在这里使用PHP -

1)在M中对值及其计数进行分类:让我们称之为C

$C = array_count_values( $M );

This gives us:
Array
(
    [1] => 3
    [2] => 3
     ...
    [20] => 1
     ...
)

2)从P中取出第一个数字并在M上应用binary search并获得最接近P1的数字N1(N1 中减去相应的计数

    So say you get 500 which is nearest to 670. Now subtract $C[500] - 1.
You can validate if count is not 0 and if zero get the next lower number from M.

3)获取P1-N1并再次二进制搜索此数字并返回最接近的值。将其添加到N1并保持循环直到获得最接近的总和。

4)对P的所有成员重复第2点和第3点。

二元搜索是这里的关键部分,应该足够高效。

答案 2 :(得分:0)

类似于硬币更改问题:http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/Greedy/greedyIntro.htm

唯一的区别是你有一个有限的“硬币”供应(可以通过将数组中的项目标记为“已使用”来轻松解决)并且您不需要达到确切的数字 - 加/减10%对你有好处(这样你就可以扔掉M中低于目标值10%的元素)