PHP-将小部件包装到最少数量的盒子中,再加上最少的订购量

时间:2019-04-03 13:13:20

标签: php algorithm

问题是这样的:

一家公司以一组包装尺寸提供小部件:

  • 250
  • 500
  • 1000
  • 2000
  • 5000

客户可以订购任意数量的小部件,但是以下规则适用:

  • 只有整包可以发送,并且……
  • 不应发送多余的小部件,并且……
  • 应该发送最少的包

一些示例显示订购的小部件数量以及正确完成订单所需的包装数量和尺寸:

  • 1(1 x 250)
  • 251(1 x 500)
  • 501(1 x 500和1 x 250)
  • 12001(2 x 5000和1 x 2000和1 x 250)

我研究了一些算法(贪婪的硬币找零,LAFF等),因为它们似乎提供了类似的解决方案。但是,理想情况下,我正在寻找一种可扩展的,面向对象的方法来解决此问题。

这是到目前为止我要提出的:

<?php

function countWidgets($amount) 
{ 
    $packs = array(5000, 2000, 1000, 500, 
                  250); 
    $packCounter = array(0, 0, 0, 0, 0); 
    $packsCount = count($packs);

    // loop packs
    for ($i = 0; $i < $packsCount; $i++)  
    { 
        if ($amount >= $packs[$i]) 
        { 
            $packCounter[$i] = intval($amount /  
                                      $packs[$i]); 
            $amount = $amount -  
                      $packCounter[$i] *  
                      $packs[$i]; 
        } 
    }

    // if remainder
    if ($amount > 0) {
        // and if smallest pack size populated
        if ($packCounter[4] == 1) {
            // clear smallest pack size
            $packCounter[4] = 0;
            // increment next biggest pack size
            $packCounter[3] += 1;
        } else {
            // increment smallest pack size
            $packCounter[4] +=1;
        }
    }


    // Print packs 
    echo ("Pack ->"."\n"); 
    for ($i = 0; $i < $packsCount; $i++)  
    { 
        if ($packCounter[$i] != 0)  
        { 
            echo ($packs[$i] . " : " . 
                  $packCounter[$i] . "\n"); 
        } 
    } 
} 

$amount = 251; 
countWidgets($amount);

1 个答案:

答案 0 :(得分:0)

好的,我同意这比我昨天假设的要难一些。您基本上有两个相反的要求:

  1. 不应该发送多余的小部件。
  2. 应该发送最少的包。

不能同时满足这两个条件。因此,如果我尝试发送1200个小部件,规则2说我应该发送2000个数据包,但是规则1说我应该发送2个数据包:1000个和250个。应该以哪个规则为准?

我选择在以下解决方案中以规则1为准。原因是没有客户想要比绝对必要更多的小部件。

$packSizes = [ 250,
               500,
              1000,
              2000,
              5000];

function optimizePacks($packSizes,$number)
{
    rsort($packSizes);
    $requiredPacks = array_fill_keys($packSizes,0);
    foreach ($packSizes as $size) {
        $packs = floor($number/$size);
        if ($packs > 0) {
            $requiredPacks[$size] = $packs;
            $number -= $packs*$size;
        }
    }
    if ($number > 0) $requiredPacks[min($packSizes)]++;
    return $requiredPacks;
}

$packs = optimizePacks($packSizes,6666);

print_r($packs);

这将适用于任何包装尺寸的阵列和任意数量的小部件。此代码的输出是:

  

数组(       [5000] => 1       [2000] => 0       [1000] => 1       [500] => 1       [250] => 1)

哪一个包比规则2要求的多一包(5000个和1000个中的两个)。当然,可以让规则2占上风,但是我不能同时满足这两个规则。