• 整数划分


    整数划分,是指把一个正整数n写成如下形式:
           n=m1+m2+...+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。
           如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<=m,则称它属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);
           例如当n=4时,结果应为,{4},{3,1},{2,2},{2,1,1},{1,1,1,1};

    在算法书上介绍的思路如下:

     根据n和m的关系,考虑以下几种情况:
            (1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
             (2) 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
             (3) 当n=m时,根据划分中是否包含n,可以分为两种情况:
                  1). 划分中包含n的情况,只有一个即{n};
                  2). 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
                  因此 f(n,n) =1 + f(n,n-1);
            (4) 当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);
            (5) 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
                   1). 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,因此这种情况下
                     为f(n-m,m)
                  2). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);
                  因此 f(n, m) = f(n-m, m)+f(n,m-1);
          综上所述:
                                 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)

    在算法书上也给出了解决的代码,但只给出了输出结果数,具体每种情况的划分是怎样的没给出代码,本人在书上代码思路的理解和参考网上部分博客后基于自己的理解给出代码如下:

    #include <iostream>  
    using namespace std;  
      
    //用于打印(输出)的函数  
    //result为存储某划分结果的数组,length为此划分所占长度-1(从0开始)  
    void display(int *result,int length)         
    {     
        for(int i=0;i<length;i++)  
            cout<<result[i]<<" ";  
        cout<<endl;  
    }  
      
    //主划分函数q(int n,int m,int *result,int length)  
    //n为待划分整数,m为最大加数上限,result和length意以同display函数  
    //将q分成五种情况分类讨论,其中包含递归调用  
    int q(int n,int m,int *result,int length)  
    {  
    //当n>=1且m=1时,q(n,m,result,length)=q(n-1,m,result,length)      
         if(n>=0&&m==1)                                                                                       
        {  
    //直至n=0且m=1时,输出  
            if(n==0)   
    		{
    			display(result,length);  
    		}  
            else  
            {  
            result[length]=1;  
            q(n-1,m,result,length+1);  
            }  
            return 1;  
        }  
    // 当 n=1且m>1 时,分解已经完成,进行输出  
        else if(n==1&&m>1)                                 
        {  
            result[length]=n;  
            display(result,length+1);  
            return 1;  
        }  
      
    //当n<m时,q(n,m,result,length)=q(n,n,result,length)  
        else if(n<m)                                        
       {  
            return q(n,n,result,length);  
        }  
      
    //当n=m时,q(n,m,result,length)=q(n,m-1,result,length)+1(划分数目)  
        else if(n==m)                                           
    {  
            result[length]=m;  
            display(result,length+1);  
            return q(n,m-1,result,length)+1;  
        }  
      
    //当n>m>1时,//q(n,m,result,length)=q(n-m,m,result,length+1)+q(n,m-1,result,length)  
        else                                                           
        {  
            result[length]=m;  
            return q(n-m,m,result,length+1)+q(n,m-1,result,length);  
        }  
    }  
      
      
      void main()  
      {  
          int n;                            //定义待划分整数  
          int result[100]={0},length=0;        //初始化  
          cout<<"please input the integer:";    
          cin>>n;  
          cout<<"整数"<<n<<"的划分个数为"<<q(n,n,result,length)<<endl;  
      }  
    程序运行结果如下:



  • 相关阅读:
    NodeJS学习笔记之Connect中间件模块(一)
    XML CDATA节点
    6个强大的AngularJS扩展应用
    java使用poi读取ppt文件和poi读取excel、word示例
    Java log4j详细教程
    JAVA8 十大新特性详解
    Express 路由
    基于 Node.js 平台,快速、开放、极简的 web 开发框架。
    Node.js 手册查询-1-核心模块方法
    Node.js 手册查询-2-MongoDB数据库方法
  • 原文地址:https://www.cnblogs.com/hainange/p/6334081.html
Copyright © 2020-2023  润新知