http://www.dewen.net.cn/q/15749/PHP求数组值相加(可重复)等于某值的所有组合

http://www.dewen.net.cn/q/15749/PHP求数组值相加(可重复)等于某值的所有组合

tieGump
1 票
tieGump 8
例如 $data = array(1,2,4);$n=10;的所有的组合有Array ( [0] => 1,1,1,1,1,1,1,1,1,1 [1] => 2,1,1,1,1,1,1,1,1 [4] => 2,2,1,1,1,1,1,1 [5] => 4,1,1,1,1,1,1 [14] => 2,2,2,1,1,1,1 [15] => 4,2,1,1,1,1 [45] => 2,2,2,2,1,1 [46] => 4,2,2,1,1 [54] => 4,4,1,1 [141] => 2,2,2,2,2 [142] => 4,2,2,2 [150] => 4,4,2 )这些,我实现了一个算法。但是当$n比较大的时候运算特别慢,用二进制key相交的方式也试了。都比较慢,求一种更好的方式。谢谢,下面是我用递归实现的一种方式。求指导。

function myAll($n, $arr) {
foreach ($arr as $v) {
$tmp = $n - $v;
if ($tmp > 0) {
foreach (myAll($tmp, $arr) as $v1) {
$tt = is_array($v1) ? array_merge(array (
$v
), $v1) : array (
$v,
$v1
);
if (array_sum($tt) == $n) {
arsort($tt);
$return[] = $tt;
}
}
} else {
if ($n == $v)
$return[] = array (
$v
);
}
}
return $return;
}

$data = array(1,2,4);
$n=10;
$tmp=myAll($n, $data);
foreach($tmp as $value){
$t[]=implode($value,',');
}
$t2=array_unique($t);
$ii=array_intersect_key($tmp,$t2);
print_r($ii);

评论 (0) • 举报 (0) • 分享 • 链接 • 2013-12-13 
添加评论...
1个答案 票 数
brayden认证专家
1 票
brayden6562
最佳答案
这个就是完全背包问题的一个变种. 即要求正好达到背包容量. 物品的价值即是其重量.

打开 背包九讲, 第一讲: http://love-oriented.com/pack/P01.html

-- 引用
"如果是第一种问法,要求恰好装满背包,那么在初始化时除了f[0]为0其它f[1..V]均设为-∞,这样就可以保证最终得到的f[N]是一种恰好装满背包的最优解。

为什么呢?可以这样理解:初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。

这个小技巧完全可以推广到其它类型的背包问题,后面也就不再对进行状态转移之前的初始化进行讲解。"
-- 引用结束

你的问题$data = array(1,2,4);$n=10, 即是背包容量为10. 物品v =[1,2,4], c=[1,2,4]的一个完全背包问题, 要求恰好装满背包.

posted @ 2016-03-10 15:31  brayden  阅读(240)  评论(0编辑  收藏  举报