整数划分 深搜(递归)

来源:互联网 发布:plc编程线 编辑:程序博客网 时间:2024/06/16 18:36

java
几个简单的问题,运用深搜(递归)解决
1. N个整数划分为K个子集
2. 在N个整数中选取M个数,使其和等指定值
3. 在N个整数中选取任意个数,使其和等于指定值
4. 在N个整数集合中,将集合划分为两部分,且子集交集为空,使其子集的和尽量相等

import java.util.Arrays;import com.util.Array;import com.util.Print;/***2017年12月20日  下午12:44:22<br>*TODO:<pre><br>  *   </pre>    Question:<pre><br>    </pre>    Analysis:<pre><br>  </pre>*/public class 整数划分{    public static void main(String[] args)    {        // s1_test();        // s2_test();        // s3_test();        s4_test();    }    public static void s1_test()    {        int i = -1;        int n = 10;        while(++i<=n+1)        {            System.out.println(n+" "+i+" "+number_split1(n,i));        }    }    /**     *  TODO:<pre>     *  N个整数划分为K个子集,每个子集不为空且两两交集为空     *求,有多少种划分方法     *考虑一个子集i,如果i单独构成一个子集,那么分法 c(n-1,k-1)     *如果i不单独构成一个子集,那么k*c(n-1,k)     *边界条件:     *( n==k||(n>0&&k==1) ) return 1;     *( n<k||(n>0&&k==0) ) return 0;     *  @param n     *  @param k     */    public static int number_split1(int n,int k)    {        if( n==k||(n>0&&k==1) ) return 1;        if( n<k||(n>0&&k==0) ) return 0;        int sum = 0;        sum = number_split1(n-1,k-1)+k*number_split1(n-1,k);        return sum;    }    static int arr[];    static int ans[];    static int tot;    public static void s2_test()    {        int len = 20,sum = 30,k = 5;        arr = Array.getRandomIntArrayNoRepeat(1,22,len);        ans = new int[k+1];        Arrays.sort(arr);        tot = 0;        Print.printArray(arr);        number_split2(sum,k,len-1);        System.out.println(tot);    }    /**     *  TODO:<pre>整数划分2     *  在N个整数中选取M个数,使其和等指定值     *  分析:     *  1.递归     *  先排序,然后对于元素i,我们考虑选取它     *  然后方程变为d(sum-i,m-1)     *  不选取:d(sum,m-1)     *  边界:     *  sum==0&&m==0  return true     *  sum<0||m<0,index<0 ||arr[index]>sum return false     *  @param sum 当前的数字和     *  @param k 选取K个整数     *  @param index 数组下标     */    public static void number_split2(int sum,int m,int index)    {        if( sum==0&&m==0 )        {            tot++;            Print.printArray(ans,1,ans.length-1);            return;        }        if( sum<0||m<0||index<0||arr[index]>sum ) return;        ans[m] = arr[index];        number_split2(sum-arr[index],m-1,index-1);        ans[m] = 0;        number_split2(sum,m,index-1);    }    public static void s3_test()    {        int len = 20,sum = 30;        arr = Array.getRandomIntArrayNoRepeat(1,22,len);        ans = new int[len];        Arrays.sort(arr);        tot = 0;        Print.printArray(arr);        number_split3(sum,0,len-1);        System.out.println(tot);    }    /**     *  TODO:<pre>     *  整数划分3                          *  在N个整数中选取任意个数,使其和等于指定值          *  @param sum 和     *  @param counter 选中的数字个数     *  @param index 数组当前下标     */    public static void number_split3(int sum,int counter,int index)    {        if( sum==0 )        {            tot++;            Print.printArray(ans,0,counter-1);            return;        }        if( sum<0||index<0||arr[index]>sum ) return;        ans[counter] = arr[index];        number_split3(sum-arr[index],counter+1,index-1);        ans[counter] = 0;        number_split3(sum,counter,index-1);    }    static int s4M = 2;// s4 阈值    public static void s4_test()    {        int len = 10,sum = 0;        arr = Array.getRandomIntArrayNoRepeat(1,10,len);        ans = new int[len];        Arrays.sort(arr);        tot = 0;        Print.printArray(arr);        for(int i = 0;i<len;i++)        {            sum += arr[i];        }        number_split4(sum/2,0,len-1);        System.out.println(tot);    }    /**     *  TODO:<pre>     *  整数划分4                         *  在N个整数集合中,将集合划分为两部分,且子集交集为空,使其子集的和尽量相等     *  如果和的差超过某个阈值,则输出不能完成信息     *  分析:     *  与上面的整数划分类似,将数组求和sum;然后number_split3(sum/2,0,len-1),     */    public static void number_split4(int sum,int counter,int index)    {        if( sum==0||Math.abs(sum)<=s4M )        {            tot++;            ans[counter] = sum;// 记录 sum相差值,数组最后一位就是差值了            Print.printArray(ans,0,counter);        }        if( index<0 ) return;        ans[counter] = arr[index];        number_split4(sum-arr[index],counter+1,index-1);        ans[counter] = 0;        number_split4(sum,counter,index-1);    }}
原创粉丝点击