整数划分问题

来源:互联网 发布:网络知识教程 编辑:程序博客网 时间:2024/06/06 01:10

               整数划分问题是一个经典问题,几乎在讲算法设计的书中都会讲,下面把主要的思想给总结下。

       所谓整数划分,就是将一个正整数n划分为一系列的正整数之和,如将n可以划分为:{m1,m2,m3,m4,m5..mk}(1=<k<=n),则{m1,m2,m3,m4,m5..mk}就是n的一个整数划分。下面我们要做的是,要找到所有的n的正整数划分。

       我们该如何找出所有的划分呢?

       我们可以先来看看整数划分的规律:

        譬如正整数:6

        划分情况如下:

        6

        5+1

        4+2   4+1+1

        3+3   3+2+1 3+1+1+1

        2+2+2 2+2+1+1 2+1+1+1+1

        1+1+1+1+1+1

         观察第一列的数字发现,我们划分过程中总是按照比6小1,小2,小3,小k,的顺序来依次排列它的划分,第一列找到比6小k的数之后,然后我们再排列剩下的数字。

         所以我们只需要找到那些比6小的数字开头的,这一行的排列的数目,然后把这些行加起来就是所有的结果,注意看每一行,划分的特征是,所有的数字都不超过第一列的那个数字,所以我们可以进行如下的尝试。

         我们试图这样去思考这个问题:

         如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<=m,则称它属于n          的一个m划分。这里我们记n的m划分的个数为f(n,m);

         例如当n=4时,他有5个划分,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};

         注意4=1+3 和 4=3+1被认为是同一个划分。

         so,该问题变得清晰了,求出n的所有划分个数,即f(n, n)。

         下面我们考虑求f(n,m)的方法;

                                    递归法

           先讨论m,n之间的大小关系:

          a.当n==1时,m无论为何值,f(n,m)=1

          b.当m==1时,n无论为何值,f(n,m)=1

          c.当n<m时,由于排列中没有负数,m多出n的数,没有了实际意义,其实本质上              还是等于f(n,n)。

          d.当m==n时,可以分两种情况考虑

              1.排列中包含n,则f(n,m)=1

               2.排列中不包含n,则问题转化为求f(n,m-1)

             根据组合数学中加法规则,应将上述两种情况加起来

             故此种情况下f(n,m)=1+f(n,m-1);

         e.当n>m时,应分两种情况考虑:

             1.排列中包含m,则排列为{m,x1,x2,x3,xk},其中{x1,x2,x3,xk}之和为n-m,

                我们注意到x1.x2,x3,xk,是不超过m的,所以对于后面这些之和为n-m的元素来                 说,它们的排列数目应该为f(n-m,m)

              2.排列中不包含m,则问题转化为f(n,m-1)

             根据组合数学中的加法原则,应将上述情况加起来:

            故此情况下的f(n,m)=f(n-m,m)+f(n,m-1);

          

          综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中a和b属于回归条件,c和d属于特殊情况,将会转换为情况e。而情况e为 通用情况,属于递推的方法,其本质主要是通过减小m以达到回归条件,从而解决问题。其递推表达式如下:

         f(n, m)=       1;                                (n=1 or m=1)

                            f(n, n);                         (n<m)

                            1+ f(n, m-1);                (n=m)

                            f(n-m,m)+f(n,m-1);       (n>m)

 

          因此我们可以给出求出f(n, m)的递归函数代码如下:

          这个是用c++实现的

//整数划分#include<iostream>using namespace std;int Partition(int n,int m){    if(n==1||m==1)  return 1;    if(n<m)         return Partition(n,n);    if(n==m)        return Partition(n,m-1)+1;    if(n>m)         return Partition(n,m-1)+Partition(n-m,m);    }int main(){    int n,m;    while(cout<<endl<<"please input two int:"<<endl&&~scanf("%d%d",&n,&m))        cout<<"The count of partition intger "<<n<<" is: "<<Partition(n,m)<<endl;            } 



 

原创粉丝点击