【发布时间】:2020-07-05 01:04:05
【问题描述】:
示例数据
对于这个问题,我们假设以下项目:
- 项目:苹果、香蕉、胡萝卜、牛排、洋葱
- 值:2、2、4、5、3
- 权重:3、1、3、4、2
- 最大重量:7
目标:
MCKP 是 Knapsack Problem 的一种类型,附加的约束是“[T]he items are subdivided into k classes...必须从每个类"
我已经编写了代码来使用递归调用和记忆化来解决动态编程的 0/1 KS 问题。我的问题是是否可以将此约束添加到我当前的解决方案中?假设我的课程是水果、蔬菜、肉类(来自示例),我需要包括每种类型的 1 个。这些类也可以是类型 1、2、3。
另外,我认为这可以通过线性规划和求解器来解决,但如果可能的话,我想在这里了解答案。
当前代码:
<?php
$value = array(2, 2, 4, 5, 3);
$weight = array(3, 1, 3, 4, 2);
$maxWeight = 7;
$maxItems = 5;
$seen = array(array()); //2D array for memoization
$picked = array();
//Put a dummy zero at the front to make things easier later.
array_unshift($value, 0);
array_unshift($weight, 0);
//Call our Knapsack Solver and return the sum value of optimal set
$KSResult = KSTest($maxItems, $maxWeight, $value, $weight);
$maxValue = $KSResult; //copy the result so we can recreate the table
//Recreate the decision table from our memo array to determine what items were picked
//Here I am building the table backwards because I know the optimal value will be at the end
for($i=$maxItems; $i > 0; $i--) {
for($j=$maxWeight; $j > 0; $j--) {
if($seen[$i][$j] != $seen[$i-1][$j]
&& $maxValue == $seen[$i][$j]) {
array_push($picked, $i);
$maxValue -= $value[$i];
break;
}
}
}
//Print out picked items and max value
print("<pre>".print_r($picked,true)."</pre>");
echo $KSResult;
// Recursive formula to solve the KS Problem
// $n = number of items to check
// $c = total capacity of bag
function KSTest($n, $c, &$value, &$weight) {
global $seen;
if(isset($seen[$n][$c])) {
//We've seen this subproblem before
return $seen[$n][$c];
}
if($n === 0 || $c === 0){
//No more items to check or no more capacity
$result = 0;
}
elseif($weight[$n] > $c) {
//This item is too heavy, check next item without this one
$result = KSTest($n-1, $c, $value, $weight);
}
else {
//Take the higher result of keeping or not keeping the item
$tempVal1 = KSTest($n-1, $c, $value, $weight);
$tempVal2 = $value[$n] + KSTest($n-1, $c-$weight[$n], $value, $weight);
if($tempVal2 >= $tempVal1) {
$result = $tempVal2;
//some conditions could go here? otherwise use max()
}
else {
$result = $tempVal1;
}
}
//memo the results and return
$seen[$n][$c] = $result;
return $result;
}
?>
我的尝试:
- 我的第一个想法是添加一个类(k)数组,通过类(k)对项目进行排序,当我们选择与下一个项目相同的项目时,检查是否保持当前更好项目或没有下一个项目的项目。看起来很有希望,但在检查了几项后就崩溃了。像这样的东西: $tempVal3 = $value[$n] + KSTest($n-2, $c-$weight[$n]); 最大值($tempVal2,$tempVal3);
- 另一个想法是,在函数调用中,我可以为每个类类型调用一个循环,并在该类型的时间只使用 1 个项目 + 其余值来解决 KS。这肯定会做出一些假设,因为例如第 1 组的结果可能仍然是第 2 组的倍数。
This looks to be the equation(如果您擅长阅读所有这些符号?):) 和 C++ 实现?但我真的看不出类约束发生在哪里?
【问题讨论】:
标签: php algorithm recursion dynamic-programming knapsack-problem