【问题标题】:Algorithm to walk through multiple array values to fill buckets in another array遍历多个数组值以填充另一个数组中的桶的算法
【发布时间】:2012-01-27 04:36:15
【问题描述】:

我想不出更好的表达方式,但这就是我想做的。我正在为购物车开发一个包优化器类。这个想法是最多 X 个不同类型的小部件可以容纳在一个容器中。问题是小部件的大小并不完全相同,所以如果说我们有项目 A(最大)、B 和 C(最小),我们必须使用 A 大小的 X-item 容器。

这是我的小部件的尺寸数组

$widgets = array('WidgetA' => 
    array (
      'length' => 10,
      'width' => 10,
      'height' => 10,
      'weight' => 10
    ),
    'WidgetB' => 
    array (
      'length' => 9,
      'width' => 9,
      'height' => 9,
      'weight' => 9
    ),
    'WidgetC' => 
    array (
      'length' => 8,
      'width' => 8,
      'height' => 8,
      'weight' => 8
    )
);

这是这些小部件的包装选项的数组,关键是相关维度支持的小部件数量,如果它是所有给定的小部件类型。

$packaging_options = array(
6 => 
array (
  'A' => 
  array (
    'length' => 100,
    'width' => 100,
    'height' => 100,
    'weight' => 100,
  ),
  'B' => 
  array (
    'length' => 90,
    'width' => 90,
    'height' => 90,
    'weight' => 90
  ),
  'C' => 
  array (
    'length' => 80,
    'width' => 80,
    'height' => 80,
    'weight' => 80
  )
),
5 => 
array (
  'A' => 
  array (
    'length' => 95,
    'width' => 95,
    'height' => 95,
    'weight' => 95,
  ),
  'B' => 
  array (
    'length' => 85,
    'width' => 85,
    'height' => 85,
    'weight' => 85
  ),
  'C' => 
  array (
    'length' => 75,
    'width' => 75,
    'height' => 75,
    'weight' => 75
  )
),
2 => 
array (
  'A' => 
  array (
    'length' => 20,
    'width' => 20,
    'height' => 20,
    'weight' => 20,
  ),
  'B' => 
  array (
    'length' => 18,
    'width' => 18,
    'height' => 18,
    'weight' => 18
  ),
  'C' => 
  array (
    'length' => 80,
    'width' => 80,
    'height' => 80,
    'weight' => 80
  )
),
1 => 
array (
  'A' => 
  array (
    'length' => 10,
    'width' => 10,
    'height' => 10,
    'weight' => 10,
  ),
  'B' => 
  array (
    'length' => 9,
    'width' => 9,
    'height' => 9,
    'weight' => 9
  ),
  'C' => 
  array (
    'length' => 8,
    'width' => 8,
    'height' => 8,
    'weight' => 8
  )
);

这里是购物车中的一系列产品示例。键是小部件 id,值是数量。

$products = array(
   'A' => 14,
   'B' => 8,
   'C' => 23
);

我最终试图得到一个由如下条目组成的 xpackages 数组:

array(
   'length' => x,
   'height' => x,
   'width' => x,
   'weight' => (sum of the individual box weights allocated to this package)
);

我只是想不出一个好方法来查看该 products 数组以分配给这些盒子。当我看它时似乎相当简单,但编码逻辑刚刚失控,我知道必须有比我接近它的方式更好的方法。我正在考虑递归,但解决方案只是不适合我。

【问题讨论】:

  • 这是一个多重背包问题,即使使用动态编程,它也有很大的解空间需要检查。您的方法(如下所述)是所谓的“贪心算法”,基本上是一种近似值,可以给出远非最佳的结果。但是应该有一种启发式方法,可以让您快速接近最佳解决方案,这应该足够好。这样的事情可能会有所帮助:Heuristics for multiple knapsack problem.

标签: php arrays algorithm recursion


【解决方案1】:

我建议您阅读背包问题。这个链接建议了一些算法来解决它。它们可以很容易地用任何语言实现。

http://en.wikipedia.org/wiki/Knapsack_problem

大多数使用动态编程的版本只考虑产品的重量。如果你多读一点关于这个问题的变体,你会发现通过向你的动态规划数组添加第三维,你可以考虑产品的体积。

希望这会有所帮助!祝你好运。


好的,我现在稍微了解您的问题了。使用类似这样的算法怎么样:

//widgets is an array of widgets sorted by volume
//count is an array holding the number of each 
Algorithm OptimizePackages(widgets[0..n-1], count[0..n-1])
    bin_stack <- initialize an empty stack of bins
    bin <- take a bin that can fit widgets[0]
    for(i = 0 to n-1) do
        for(j = 0 to count[i]) do
            if(bin.available_volume < widgets[i].volume) then
                bin_stack.push(bin)
                bin <- take a bin that can fit widgets[i]
            end if

            bin.add(widgets[i])
            bin.available_volume -= widgets[i].volume
        end
    end
    return bin_stack.to_array()

此算法的一个限制是它可能会在某些垃圾箱上留下少量可用体积。如果你有时间做它需要的大脑体操,你可以调整它以消除这个限制;)

【讨论】:

  • 感谢您的链接并给我一个正确的名称。我并没有真正尝试对垃圾箱或产品尺寸进行数学计算。我已经根据体积对它们进行了预分类,所以它只是遍历产品阵列并将它们扔到我当前所在的垃圾箱中。我只是对如何填充部分垃圾箱有疑问。假设 bin 包含 12 个小部件……如果我只有 6 个,我需要将这 6 个放入,然后转到列表中的下一个产品并从中放入 6 个,等等。
【解决方案2】:

这是一个多重背包问题,它有一个非常大的解决方案空间来检查,而且动态规划都没有多大帮助(取决于你的问题的大小)。

您的方法(在您的评论中解释)是所谓的“贪婪启发式算法”,基本上是一种可以快速给出结果的近似值,但在很多情况下远非最优。有一些更好的启发式方法可以让您快速接近最佳解决方案,这应该足够好。

这样的事情可能会有所帮助:Heuristics for multiple knapsack problem

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2022-01-06
    • 2014-09-02
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多