内容简介:代码日志版权声明:翻译自:http://stackoverflow.com/questions/13211189/calculate-which-products-together-would-deliver-the-requested-power
假设我有三个产品:
产品A
将提供5个电源.成本50.
产品B将提供9个电源.成本80.
产品C将提供15个电源.成本140.
当我需要7个电源时,我想知道我可以购买什么产品的组合.我可以买到两个A,但是B中的一个是便宜的.
当我需要65个电源我需要4次C和1次A(费用680).但我也可以去七个B产品和一个A(费用610).
我正在寻找一种方法来计算我需要的给定功率的产品的可能组合.
我这样做的方式不会给我我想要的:
// $products are sorted DESC on their $power
$power = 65
while( $power > 0 ) {
foreach( $products as $productPower ) {
if( ( $productPower > $power && $power - $productPower > 0 ) || $productPower == end( $products ) ) {
// Add product to list
$power -= $productPower;
break;
}
}
}
这个示例代码只会给我4次C和一次A.我该怎么办?
编辑产品数量是可变的.此外,具体成本和功率是可变的.所以可能会有10个产品与cheeper和更昂贵的价格标签.
编辑2如上所述,我想计算可能的组合(复数).有些人似乎在我的描述中错过了.
介绍
这将是一个 Knapsack problem ,但因为你不只是寻找最佳的解决方案,你也想找到所有可能的组合
那么你可以解决这个 Subset sum problem Coin Change 得到:
>列出所有可能的组合,而不仅仅是总组合
>获得最佳组合
例如,对于N = 4,S = {1,2,3},有四个解:{1,1,1,1},{1,1,2},{2,2},{1, 3}.
实施例1
echo "<pre>";
$start = microtime(true);
// Start Finder
$finder = new CombinationFinder(65);
// Add Produts
$finder->addProduct(new Product("A", 5, 50));
$finder->addProduct(new Product("B", 9, 80));
$finder->addProduct(new Product("C", 15, 140));
// Output All Found Combinations
foreach ( $finder as $key => $sales ) {
echo $sales->getName(), "\t\t\t", $sales->getCombinationCost(), PHP_EOL;
}
// Get Best Combination
echo "Combination: ", $finder->getBestCombination()->getName(), PHP_EOL;
echo "Cost: ", number_format($finder->getBestCombination()->getCombinationCost(), 2), PHP_EOL;
// Total Time
echo PHP_EOL, microtime(true) - $start;
产量
顶级组合
["A",1],["C",4] 610 ["A",1],["B",5],["C",1] 590 ["A",4],["C",3] 620 ["A",4],["B",5] 600 ["A",7],["C",2] 630 ["A",10],["C",1] 640 ["A",13] 650
最佳组合
Combination: ["A",1],["B",5],["C",1] Cost: 590.00
总时间
0.2533269405365
最佳组合
你可以看到最好的组合是A * 1,B * 5,C * 1 ..分解
A B C Power : 5 * 1 + 9 * 5 + 15 * 1 = 65 Cost : 50 * 1 + 80 * 5 + 140 * 1 = 590 <---- Better than 610.00
实施例2
该类可以用于2,3,4或更多的产品组合,并且非常快
echo "<pre>";
$start = microtime(true);
// Start Finder
$finder = new CombinationFinder(65);
// Add Produts
$finder->addProduct(new Product("A", 5, 50));
$finder->addProduct(new Product("B", 9, 80));
$finder->addProduct(new Product("C", 15, 140));
$finder->addProduct(new Product("D", 20, 120)); // more product class
$finder->run(); // just run
// Get Best Combination
echo "Combination: ", $finder->getBestCombination()->getName(), PHP_EOL;
echo "Cost: ", number_format($finder->getBestCombination()->getCombinationCost(), 2), PHP_EOL;
// Total Time
echo PHP_EOL, microtime(true) - $start;
产量
Combination: ["A",1],["D",3] //<---------------------- Best Combination Cost: 410.00
所用的时间
1.1627659797668 // less than 2 sec
使用类
class Product {
public $name;
public $power;
public $cost;
public $unit;
function __construct($name, $power, $cost) {
$this->name = $name;
$this->power = $power;
$this->cost = $cost;
$this->unit = floor($cost / $power);
}
}
class Sales {
/**
*
* @var Product
*/
public $product;
public $count;
public $salePower;
public $saleCost;
function __construct(Product $product, $count) {
$this->product = $product;
$this->count = $count;
$this->salePower = $product->power * $count;
$this->saleCost = $product->cost * $count;
}
}
class SalesCombination {
private $combinationPower;
private $combinationCost;
private $combinationName;
private $combinationItems;
private $args;
function __construct(array $args) {
list($this->combinationPower, $this->combinationCost, $this->combinationItems) = array_reduce($args, function ($a, $b) {
$a[0] += $b->salePower;
$a[1] += $b->saleCost;
$a[2] = array_merge($a[2], array_fill(0, $b->count, $b->product->name));
return $a;
}, array(0,0,array()));
$this->args = $args;
}
function getName() {
$values = array_count_values($this->combinationItems);
$final = array();
foreach ( $values as $name => $amount ) {
$final[] = array($name,$amount);
}
return substr(json_encode($final), 1, -1);
}
function getCombinationPower() {
return $this->combinationPower;
}
function getCombinationCost() {
return $this->combinationCost;
}
}
class CombinationFinder implements IteratorAggregate, Countable {
private $sales;
private $products = array();
private $power;
private $found = array();
private $bestCombination = null;
private $run = false;
function __construct($power) {
$this->power = $power;
}
function addProduct(Product $product) {
$this->products[] = $product;
}
function getBestCombination() {
return $this->bestCombination;
}
function getFound() {
return $this->found ? : array();
}
public function getIterator() {
if ($this->run === false) {
$this->run();
}
return new ArrayIterator($this->found);
}
public function count() {
return count($this->found);
}
function run() {
$this->run = true;
$this->buildSales();
$u = new UniqueCombination($this->sales);
$u->setCallback(array($this,"find"));
$u->expand();
}
function find() {
$salesCombination = new SalesCombination(func_get_args());
if ($salesCombination->getCombinationPower() == $this->power) {
isset($this->bestCombination) or $this->bestCombination = $salesCombination;
$salesCombination->getCombinationCost() < $this->bestCombination->getCombinationCost() and $this->bestCombination = $salesCombination;
$this->found[sha1($salesCombination->getName())] = $salesCombination;
}
}
function buildSales() {
$total = count($this->products);
foreach ( $this->products as $product ) {
$max = floor($this->power / $product->power);
for($i = 1; $i <= $max; $i ++) {
$this->sales[$product->name][] = new Sales($product, $i);
}
}
}
}
class UniqueCombination {
private $items;
private $result = array();
private $callback = null;
function __construct($items) {
$this->items = array_values($items);
}
function getResult() {
return $this->result;
}
function setCallback($callback) {
$this->callback = $callback;
}
function expand($set = array(), $index = 0) {
if ($index == count($this->items)) {
if (! empty($set)) {
$this->result[] = $set;
if (is_callable($this->callback)) {
call_user_func_array($this->callback, $set);
}
}
return;
}
$this->expand($set, $index + 1);
foreach ( $this->items[$index] as $item ) {
$this->expand(array_merge($set, array($item)), $index + 1);
}
}
}
代码日志版权声明:
翻译自:http://stackoverflow.com/questions/13211189/calculate-which-products-together-would-deliver-the-requested-power
以上所述就是小编给大家介绍的《php – 计算哪些产品在一起将提供所要求的电力》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 华能国际:中国电力企业领导者
- 海量电力设备监测数据的存储和特征分析
- 电力运维无从着手?物联网开启新入口
- 云化的调控中心助力上海电力智能化转型
- 攻防最前线:通过电力线“搞定”物理隔离计算机
- 泛在电力物联网时代,杰思猎鹰护航电网主机安全
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++面向对象程序设计
萨维奇 (Walter Savitch) / 周靖 / 清华大学出版社 / 2003-12 / 59.0
《C++面向对象程序设计》具备良好的编排体系,适合打算涉足编程领域的读者阅读,尤其适合大一学生。它最大的特色是Savitch教授最受欢迎的写作风格,这一风格非常适合初学者,能迅速引导他们开始编程实践。《C++面向对象程序设计》包括全面的习题、项目、编程提示、编程示例、编程陷阱以及有用的小结,以帮助初学者更清楚地了解C++。一起来看看 《C++面向对象程序设计》 这本书的介绍吧!