今天一个朋友问了我这个问题,研究了一下,代码如下,应该能符合题主的要求,虽然时间已经过去很久了。
// 目标数组
$arr = [15, 20, 10, 6];
// 限定最大值
$max = 38;
// 执行
$re = digui($arr, $max);
// 执行结果
print_r('当限定结果最大值为 ' . $max . ' 时,最优解为' . implode('+', $re[1]) . '=' . $re[0]);
// 程序主体
function digui($arr, $max = null, $re = [], $i = 0, $bak = []) {
empty($bak) && $bak = $arr;
if (count($arr) == 0) {
// 递归结束,返回解析结果集
if (empty($re)) {
return [0, []];
}
krsort($re);
foreach ($re as $k1 => $v1) {
// 将序列转换为数字
foreach ($v1 as $k2 => $v2) {
$v1[$k2] = $bak[$v2];
}
// 最终返回结果
return [$k1, $v1];
}
}
// 取出当前第一个数
$x = array_shift($arr);
// 单元素
if (!isset($re[$x])) {
if ($x > $max) {
$i++;
return digui($arr, $max, $re, $i, $bak);
}
if ($x == $max) {
$re = [$x => [$x]];
return digui([], $max, $re, $i, $bak);
}
$re[$x] = [$i];
}
// 双元素相加
for ($b = 0; $b < count($arr); $b++) {
$result = $x + $arr[$b];
if (!isset($re[$result])) {
if ($result < $max) {
$re[$result] = [$i, $i + $b + 1];
}
if ($result == $max) {
$re = [$result => [$i, $i + $b + 1]];
return digui([], $max, $re, $i, $bak);
}
}
}
// 多元素相加
foreach ($re as $k => $v) {
if (count($v) > 1 && !in_array($i, $v)) {
$result = $k + $x;
if (!isset($re[$result])) {
array_push($v, $i);
if ($result < $max) {
$re[$result] = $v;
}
if ($result == $max) {
$re = [$result => $v];
return digui([], $max, $re, $i, $bak);
}
}
}
}
$i++;
return digui($arr, $max, $re, $i, $bak);
}