在算法书上介绍的思路如下:
根据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; }程序运行结果如下: