设为首页 加入收藏

TOP

递归(二):正整数的拆分(一)
2019-06-25 22:06:28 】 浏览:139
Tags:递归 整数 拆分

【例1】求正整数的拆分数。

      将正整数s表示成一系列正整数之和,s=n1+n2+…+nk,其中n1>=n2>=…>=nk, k>=1。正整数s的不同拆分个数称为s的拆分数。例如,正整数6有11种不同的拆分,分别是:

      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。

      (1)编程思想。

      设m、n均为正整数,m可表示为一些不超过n的正整数之和,f(m,n)为这种表示方式的数目。下面先确定递归关系。

      如果 n>m,则拆分式中n、n-1、…、m+2、m+1这n-m 个数必定不会出现,去掉它们对拆分式的表示数目不产生影响;即    f(m,n) = f(m,m)。

      如果 n=m,则 f(n,m)=1+f(n,n?1)。 其中,“1”表示n的拆分式中只包含n本身,即n=n,只有一种拆分表示;f(n,n?1)表示n的所有其他拆分,即拆分式中最大正整数不超过n?1的拆分数目。

      如果n<m,则  f(n,m)=f(n,m?1)+f(n?m,m)。其中,f(n,m?1)表示拆分式中不包含m的拆分式数目;f(n?m,m)表示拆分式中至少包含一个m的拆分数目,因为如果确定了一个拆分式中包含正整数m,则剩下的部分就是对n?m进行不超过m的拆分。

       确定递归的终止条件。第一个终止条件:f(n,1)=1,表示当拆分式中最大的正整数是1时,该整数n只有一种拆分,即n个1相加。第二个终止条件:f(1,m)=1,表示整数n=1只有一个拆分,不管上限m是多大。

      (2)源程序。

#include <iostream>
using namespace std;
int f(int m,int n)
{
    if(m==1 || n==1)
        return 1 ;
    if(m<n)
        return f(m,m);
    if (m==n)
       return 1+ f(m,n-1);
    return f(m,n-1)+f(m-n, n );
}
int main()
{
    int n, m,k;
    while (cin >>m>>n && n!=0)
    {
         k=f(m,n);
        cout<<k<<endl;
    }
    return 0;
}

【例2】正整数的拆分式。

      正整数s(简称为和数)的拆分是把s分成为某些指定正整数(简称为零数)之和,拆分式中不允许零数重复,且不记零数的次序。

      把指定正整数s拆分为1~m(m<=s)之和,共有多少种不同的拆分方式?输出所有这些拆分式。

      例如,若s=6,m=6,则例1中的11个拆分式只有4个符合本题的要求。即 6;  5+1;  4+2;   3+2+1。

       (1)编程思路。

       由于正整数的拆分与拆分式中各零数的排列顺序无关,因此,可以将正整数s拆分式表示成一系列从大到小排列的正整数之和,即 s=n1+n2+…+nk,其中m>=n1>n2>…>nk>=1, k>=1。

       拆分式中的k个零数都在1~m之间,因此我们需要先解决如何从1~m这m个数中取k(k<m)个数的所有组合。

       设 comb(int a[],int m,int k)为从1~m这m个数中取k个数的所有组合结果。组合的结果保存在数组元素a[1]~a[k]中,数组元素a[0]表示组合结果中元素的个数,显然,a[0]=k。

       为求解comb(int a[],int m,int k),可以先将k个数字组合的第一个数字i放在a[k]中,第一个数字i可以是m,m-1,…,k。注意:第一个数字i不能取k-1,因为后面的数字都会取比第一个数字小的数字,因此最多只能取出1~k-1共k-1个不同的数,达不到取k个数的目的。

       在将确定组合的第一个数字放入数组后,有两种选择:还未确定组合的其余元素时(k>1,即还需取k-1个元素),继续递归comb(a,i-1,k-1)确定组合的其余元素,即在1~i-1中取k-1个数;已确定组合的全部元素时(k==1),输出这个组合。

       实现这一取数组合的递归函数可设计为:

void comb(int a[],int m,int k)
{
    int i,j;
    for (i=m;i>=k;i--)
    {
        a[k]=i;
        if(k>1)
            comb(a,i-1,k-1);
        else
        {
              for (j=a[0];j>=1;j--)
                  cout<<a[j]<<" ";
              cout<<endl;
         }
     }
}

       解决了组合取数

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇超级简单的跨平台高性能音视频播.. 下一篇递归(一):递归的基本思想

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目