问题:1000个苹果分成10堆,可以组合任意1-1000个数的苹果
此问题是否有解?如何求解?
1.首先我们必须写一个验证的程序
/**
* 验证数组
* @author syh
* @param array $arr
* @return bool
*/
function check($arr)
{
rsort($arr);//逆序
$listNum=range(1,array_sum($arr));
$fun=function ($num) use ($arr){
foreach ($arr as $key => $val)
{
if($num===$val) return true;
//减去数组中比自己小的最大值
if($num>$val) $num=$num-$val;
}
return false;
};
return !in_array(false,array_map($fun,$listNum));
}
$arr=[1,2,4,8,16,32,64,128,256,489];//此数组为正解的一种,可以通过验证
$data=check($arr);
var_dump($data);//true
2.遍历所有可能的组合或随机取值
2.0非递归遍历(最原始的实现)
/**
* $m个苹果分为4堆
* @author syh
* @param int $m苹果总数
* @return array 验证通过后的数组
*/
function test($m)
{
$listAll=[];
$list=[];
$len=4;//苹果堆数
$max=function($list) use ($m,$len){
return $m-array_sum($list)-($len-count($list))+1;
};
for ($k1=1,$max1=$max($list);$k1 <=$max1; $k1++)
{
$list[1]=$k1;
for ($k2=1,$max2=$max($list);$k2 <=$max2 ;$k2++)
{
$list[2]=$k2;
for ($k3=1,$max3=$max($list);$k3 <=$max3; $k3++)
{
$list[3]=$k3;
$list[4]=$m-array_sum($list);
if(check($list))
{
$listAll[]=$list;
}
unset($list[3]);
unset($list[4]);
}