【问题标题】:Calculating maximum package size (in PHP)计算最大包大小(在 PHP 中)
【发布时间】:2010-01-02 23:46:58
【问题描述】:

为此使用 PHP。

从一组给定的物品中,每个物品都有自己的重量,我需要自动计算将物品打包成 100 磅包裹的最有效方式(最大包裹重量 100 磅是静态的,但将来可以更改)。单个包裹不能超过规定的最大值。

例如,我有 5 件物品 - 总重量为 254 磅:

  • 第 1 项 -> 51 磅
  • 第 2 项 -> 28 磅
  • 第 3 项 -> 73 磅
  • 第 4 项 -> 51 磅
  • 第 5 项 -> 51 磅

假设 254 磅需要 3 x 100 磅的包裹。此示例有意证明并非总是如此。某些项目配置无法很好地协同工作。此示例在其最佳配置中需要 4 x 100 磅的包裹。

商品数量和重量完全可变,单件商品不会超过 100 磅。

实现这一目标的最佳方式是什么?

【问题讨论】:

    标签: php algorithm


    【解决方案1】:

    您描述的问题称为Bin Packing Problem。没有人知道解决它的最佳方法。如果他们这样做了,他们将能够证明 P=NP 或 P!=NP - 计算领域的重大开放性问题之一。

    维基百科页面包含对一些示例算法的引用 - 首次拟合算法、最佳拟合递减、首次拟合递减。一般来说,解决这个问题的一种快速方法不是试图找到最优解,而是找到一个好的近似值。 “减少”是指最好先包装最大、最尴尬的元素,然后在最后用小元素填充间隙。这实际上类似于大多数人通常处理此问题的方式。

    对于您在示例中给出的问题的大小,仅通过检查所有可能的排列即可轻松找到最佳解决方案,但显然对于较大的示例而言效率不高。

    【讨论】:

    • +1,几年前我在某处读到,通过使用您描述的第一次拟合算法,结果不会比最佳解决方案差 14% 以上。很抱歉,我现在无法命名引文。
    • 有趣的是,我已经实现了自己描述的 First-Fit 算法。它在大多数情况下工作得很好。我现在的计划是实施递减拟合算法,或者通过获取最佳结果来运行项目 - 或者只是随着时间的推移分析输出以查看哪个最适合数据。谢谢。
    【解决方案2】:

    问题其实和这里讨论的一样:

    Convert function from recursion to iteration

    盲搜索方法是应用每一个包组合,这将创建一个 N 阶算法!需要超过 360 万)

    根据我在那里的帖子,请参阅

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

    对于非穷举算法的描述。

    C.

    【讨论】:

      【解决方案3】:

      对于那些感兴趣的人,这是我为解决我的问题而编写的代码:

          //Loop thru cart items - adding weights to packages
          foreach((array)$this->cart_items as $cart_item) {
              for ($i = 0; $i < $cart_item->quantity; $i++) {
      
                  $itemWeight = $cart_item->weight;   //Get current item weight
                  $currWeight += $itemWeight;             //Add item weight to active package
      
                  if ($currWeight > 100){                     //Max weight reached for active package
      
                      $currWeight -= $itemWeight;         //Remove item from current package, too heavy
                      $loopPack = 0;                                  
                      $itemUsed = false;
      
                      //Check if an existing package can take the item
                      while (($loopPack != $packageCount) or ($itemUsed = false)) {
                          if ($packages[$loopPack] + $itemWeight < 100) {
                              $packages[$loopPack] += $itemWeight;
                              $itemUsed = true;
                          }
                          $loopPack++;
                      }
      
                      //if the item didn't fit in an existing package, create a new package for it
                      if ($itemUsed == false) {
                          $packageCount++;
                          $packages[$packageCount-1] = $currWeight;
                          $currWeight = $cart_item->weight;           //Put unused item back in active package            
                      }
      
                  }
              }
          }
          //The remainder becomes a package
          $packageCount++;
          $packages[$packageCount-1] = $currWeight;
      
          print_r($packages);
      

      【讨论】:

        猜你喜欢
        • 2013-03-22
        • 1970-01-01
        • 1970-01-01
        • 2019-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多