mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-10 17:28:40 +00:00
101 lines
2.4 KiB
PHP
Executable File
101 lines
2.4 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Jingga
|
|
*
|
|
* PHP Version 8.2
|
|
*
|
|
* @package phpOMS\Algorithm\Knapsack
|
|
* @copyright Dennis Eichhorn
|
|
* @license OMS License 2.0
|
|
* @version 1.0.0
|
|
* @link https://jingga.app
|
|
*/
|
|
declare(strict_types=1);
|
|
|
|
namespace phpOMS\Algorithm\Knapsack;
|
|
|
|
/**
|
|
* Bounded knapsack algorithm
|
|
*
|
|
* This algorithm only works for integer cost, values and quantities!
|
|
*
|
|
* @package phpOMS\Algorithm\Knapsack
|
|
* @license OMS License 2.0
|
|
* @link https://jingga.app
|
|
* @since 1.0.0
|
|
*/
|
|
final class Bounded
|
|
{
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @since 1.0.0
|
|
* @codeCoverageIgnore
|
|
*/
|
|
private function __construct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Fill the backpack with items
|
|
*
|
|
* This algorithm only works for integer cost, values and quantities!
|
|
*
|
|
* @param array $items Items to fill the backpack with ['item' => Item, 'quantity' => ?]
|
|
* @param BackpackInterface $backpack Backpack to fill
|
|
*
|
|
* @return BackpackInterface
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
public static function solve(array $items, BackpackInterface $backpack) : BackpackInterface
|
|
{
|
|
$n = \count($items);
|
|
|
|
// @var int<0, max> $maxCost
|
|
$maxCost = (int) $backpack->getMaxCost();
|
|
$mm = \array_fill(0, ($maxCost + 1), 0);
|
|
$m = [];
|
|
$m[0] = $mm;
|
|
|
|
for ($i = 1; $i <= $n; ++$i) {
|
|
$m[$i] = $mm;
|
|
|
|
for ($j = 0; $j <= $maxCost; ++$j) {
|
|
$m[$i][$j] = $m[$i - 1][$j];
|
|
|
|
for ($k = 1; $k <= $items[$i - 1]['quantity']; ++$k) {
|
|
if ($k * ((int) $items[$i - 1]['item']->getCost()) > $j) {
|
|
break;
|
|
}
|
|
|
|
$v = $m[$i - 1][$j - $k * ((int) $items[$i - 1]['item']->getCost())] + $k * ((int) $items[$i - 1]['item']->getValue());
|
|
|
|
if ($v > $m[$i][$j]) {
|
|
$m[$i][$j] = $v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$s = 0;
|
|
for ($i = $n, $j = $maxCost; $i > 0; --$i) {
|
|
$s = 0;
|
|
$v = $m[$i][$j];
|
|
|
|
$value = (int) $items[$i - 1]['item']->getValue();
|
|
|
|
for ($k = 0; $v !== $m[$i - 1][$j] + $k * $value; ++$k) {
|
|
++$s;
|
|
$j -= (int) $items[$i - 1]['item']->getCost();
|
|
}
|
|
|
|
if ($s > 0) {
|
|
$backpack->addItem($items[$i - 1]['item'], $s);
|
|
}
|
|
}
|
|
|
|
return $backpack;
|
|
}
|
|
}
|