(转)php排列组合 1到9数字相加都等于20

<?php
set_time_limit(0);
/*
函数说明:huoqu_zhuhe($total,$num_array,$isone=0)
参数说明:$total---几个数相加的总和;
                  $num_array-------加数数组:$num_array=array(1,2,3,4,5,6,7,8,9),可以使用的加数;
                  $count 几个数相加,为零不限制
                  $isone---是否要每次使用不同的加数,唯一性,1是 0 不,默认1

返回类型:数组,数字以+相连的字符串:[0] => 3+8+9 [1] => 4+7+9

测试效果:1:对于加数数组比较小的,速度可以,过大的话,有些慢;2:每次可以使用不同的加数的,处理会变慢
采用的方法是:生成所有可能排列,对排列处理过滤重复的,得到组合
*/
function huoqu_zhuhe($total, $num_array, $count = 0, $isone = 1){
        if(empty($num_array) || !is_array($num_array)) {
                echo 'error:加数必须数组';return false;
        }
        $feishu=0;
        for($i=0; $i<count($num_array); $i++) {
                if(!is_numeric($num_array[$i])) {
                        $feishu=1;
                        break;
                }
        }

        if($feishu==1) {
                echo 'error;数组中必须是合法的数字';return false;
        }
        $lian=$num_array;
        $savearr=array();
        while(!empty($lian)) {
                //echo 1;
                $newarr=array();
                $k=0;
                for($i=0; $i<count($lian); $i++) {
                        $lianstr = $lian[$i];
                        $arr = explode('+', $lianstr);

                        $nowhe=array_sum($arr);
                        for($j=0;$j<count($num_array);$j++) {
                                $savestr=$lianstr.'+'.$num_array[$j];
                                if($isone==1 && in_array($num_array[$j],$arr))
                                        continue;
                                if(($nowhe+$num_array[$j])>$total)
                                        break;
                                else if(($nowhe+$num_array[$j])==$total) {
                                        $savearr[]=$savestr;
                                }else{
                                        $newarr[$k]=$savestr;$k++;
                                }
                        }//end for($j=0;$j<count($num_array)
                }// end for($i=0;$i
                $lian=$newarr;
        }//end while(!empty($lian))

        if ($count != 0) {
                foreach ($savearr as $key => $number) {
                        $savearr_count = count(explode('+', $number));
                        if ($count != $savearr_count)
                                unset($savearr[$key]);
                }
        }

        //生成组合部分,过滤重复,2个数组以一个为参考,看另一个是否能通过移动达到匹配,可以,过滤

        $isguolu=array();//存储对应的id的取舍 0取 1舍
        for($i=0;$i<count($savearr);$i++) {
                $isguolu[]=0;
        }//初始化全部0

        for($i=0;$i<count($savearr);$i++) {
                $arr1=explode('+',$savearr[$i]);
                $len1=count($arr1);
                for($j=$i+1;$j<count($savearr);$j++) {
                        $arr2=explode('+',$savearr[$j]);
                        $len2=count($arr2);
                        if($len1!=$len2)
                                continue;
                        if($isguolu[$j]==1)
                                continue;
                        //比较$arr1和$arr2开始
                        $jishu=0;
                        for($i1=0;$i1<count($arr1);$i1++) {
                                $a=$arr1[$i1];
                                $isyou=0;
                                
                                for($i2=$i1;$i2<count($arr2);$i2++) {
                                        if($a==$arr2[$i2]) {
                                                $jishu++;
                                                $isyou=1;
                                                $t=$arr2[$i1];
                                                $arr2[$i1]=$arr2[$i2];
                                                $arr2[$i2]=$t;
                                                break;
                                        }
                                }//end for($i2=0

                                if($isyou==0)break;

                        }// end for($i1=0;$i1<count($arr1);

                        if($jishu==$len1)$isguolu[$j]=1;

                }//end for($j=$i+1;

        }//end for($i=0;$i<count($savearr);$i++)
        //print_r($isguolu);
        
        //根据过滤数组选择
        $newarr=array();
        for($i=0;$i<count($savearr);$i++) {
                if($isguolu[$i]==0)$newarr[]=$savearr[$i];
        }
        //print_r($newarr);
        return $newarr;
}

//下面是一个测试
//取用1,2,3,4,5,6,7,8,9相加所有等于20的组合
$num_array=array(1,2,3,4,5,6,7,8,9,10);
if($jieguo=huoqu_zhuhe(20,$num_array,4)) {
        echo '<pre>';
        print_r($jieguo);
}
 

?>

  


posted @ 2011-10-17 16:58  末世  阅读(287)  评论(0编辑  收藏  举报