Php 求解最优组合数的算法——装箱问题
假设我有以下措施: 八十 180 200 240 410 50 110 我可以存储每个数字组合,每个单元最多480个。我如何计算所需的最少数量单位,以便以最有效的方式传播所有措施 我已经标记了PHP,但也可以是JS,甚至是伪语言 我知道我应该告诉你我已经做了什么,但我一直在思考如何处理这个问题。我想到的第一件事是递归,但我不是数学专家,不知道如何高效地实现它 非常感谢您的帮助 更详细地说:我正试图根据墙壁所需的不同长度来计算我必须订购的踢脚线数量。每条踢脚线的长度为480cm,我想知道铺踢脚线的最佳方式,因此我必须购买最少数量的踢脚线。这并不是说要额外订购一条裙子,但要想弄明白它是一个有趣的难题(至少对我来说) 使用解决方案更新 尽管人们试图解决这个问题,我还是开始摆弄箱子包装问题的描述,并遵循将所有物品从最大到最小进行排序,然后以尽可能最佳的方式将其放入的想法,我创建了这个小类,将来可能会帮助其他人:Php 求解最优组合数的算法——装箱问题,php,algorithm,math,Php,Algorithm,Math,假设我有以下措施: 八十 180 200 240 410 50 110 我可以存储每个数字组合,每个单元最多480个。我如何计算所需的最少数量单位,以便以最有效的方式传播所有措施 我已经标记了PHP,但也可以是JS,甚至是伪语言 我知道我应该告诉你我已经做了什么,但我一直在思考如何处理这个问题。我想到的第一件事是递归,但我不是数学专家,不知道如何高效地实现它 非常感谢您的帮助 更详细地说:我正试图根据墙壁所需的不同长度来计算我必须订购的踢脚线数量。每条踢脚线的长度为480cm,我想知道铺踢脚线的
<?php
class BinPacker {
private $binSize;
public function __construct($binSize) {
$this->binSize = $binSize;
}
public function pack($elements) {
arsort($elements);
$bins = [];
$handled = [];
while(count($handled) < count($elements)) {
$bin = [];
foreach($elements as $label => $size) {
if(!in_array($label, $handled)) {
if(array_sum($bin) + $size < $this->binSize) {
$bin[$label] = $size;
$handled[] = $label;
}
}
}
$bins[] = $bin;
}
return $bins;
}
public function getMeta($bins) {
$meta = [
'totalValue' => 0,
'totalWaste' => 0,
'totalBins' => count($bins),
'efficiency' => 0,
'valuePerBin' => [],
'wastePerBin' => []
];
foreach($bins as $bin) {
$value = array_sum($bin);
$binWaste = $this->binSize - $value;
$meta['totalValue'] += $value;
$meta['totalWaste'] += $binWaste;
$meta['wastePerBin'][] = $binWaste;
$meta['valuePerBin'][] = $value;
}
$meta['efficiency'] = round((1 - $meta['totalWaste'] / $meta['totalValue']) * 100, 3);
return $meta;
}
}
$test = [
'Wall A' => 420,
'Wall B' => 120,
'Wall C' => 80,
'Wall D' => 114,
'Wall E' => 375,
'Wall F' => 90
];
$binPacker = new BinPacker(488);
$bins = $binPacker->pack($test);
echo '<h2>Meta:</h2>';
var_dump($binPacker->getMeta($bins));
echo '<h2>Bin Configuration</h2>';
var_dump($bins);
虽然数据集相对较小,但满足了相当高的无效率。但在我自己的配置中,我输入了所有的墙壁和天花板措施,我的效率达到了94.212%
(n=129措施)
(注意:该类不检查模糊标签,因此,例如,如果您两次定义墙A
,则结果将不正确。)
结论:对于天花板和墙壁踢脚板,我可以订购一个比我手动尝试有效展开踢脚板少的踢脚板。在我看来,这就像是一个变化,您试图选择480(或略低于480)的元素组合。这是一个在计算上相当困难的问题,根据它需要的效率/准确度,试图获得准确度可能有点过头了
一个粗略的启发式方法可能只是对度量值进行排序,不断地将最小的度量值添加到一个单元中,直到下一个度量值让您进行检查,然后添加到一个新单元并重复 很难理解你所说的“以最有效的方式传播”是什么意思。你能用更正式的方式陈述你的问题吗?也许算法属于其他地方,比如,既然你说它更像是一个算法而不是编程问题。我给这个问题添加了上下文。或者,我发现很难通过这个问题来判断。是的,装箱问题更准确,我会编辑我的答案。谢谢这两个,装箱问题准确地描述了我想要弄明白的东西。
Meta:
array (size=6)
'totalValue' => int 1199
'totalWaste' => int 265
'totalBins' => int 3
'efficiency' => float 77.898
'valuePerBin' =>
array (size=3)
0 => int 420
1 => int 465
2 => int 314
'wastePerBin' =>
array (size=3)
0 => int 68
1 => int 23
2 => int 174
Bin Configuration
array (size=3)
0 =>
array (size=1)
'Wall A' => int 420
1 =>
array (size=2)
'Wall E' => int 375
'Wall F' => int 90
2 =>
array (size=3)
'Wall B' => int 120
'Wall D' => int 114
'Wall C' => int 80