《计算机算法设计与分析》第三版递归与分治章节 有一个整数划分问题。
将正整数n表示成一系列正整数值和: n = n1+n2+....+nk。
正整数n的这种表示称为正整数的n的划分。正整数n的不同的划分个数称为正整数的n的划分数,将最大加数记作m,记作p(n,m)。
例如:
6; a
5+1; b
4+2, 4+1+1; c
3+3, 3+2+1,3+1+1+1; d
2+2+2,2+2+1+1,2+1+1+1+1; e
1+1+1+1+1+1; f
可能我们已经注意到划分的规律了,这么多中表示方式中都有一个最大值,我们记作m,我们可以不断分治缩小最大值的,来找到如下递归规律。
n表示正整数,而m表示n由不同系列正整数组成当中的最大值。而m的最大值为n,所以我们的思想是先将m设为n,再次递减m(直至m=1为止【最大值为1的话,就一种方案,全为 1】),不断求的划分的方案。
1 . n==1 或 m == 1 任何正整数只有一种划分方式 n = 1+1+...+1 其中有m个1
2 . m >= n 最大值等于n,说明其他比较小的值都为0,所以划分方式只有一种 n = m.
所以p(n.m)= 1+p(n,m-1);而m-1肯定是小于n的。
3 . m( 将2中的m-1当做一个整体 ) < n,又有以下的规律 p(n,m) = p(n,m-1)+p(n-m,m)
详细说明p(n,m-1)和p(n-m,m)。 p(n,m-1)我们说过需要不断的递减m,直至m到1为止。这就是我们前面说的方案。比如看到我们的6从6,5,4,3,2,1递减,a-f。
p(n-m,m),当 m<n的时候,我们就要执行这句。从b中,6=5+1,我们还需要分配1这个方案。4+1+1,。3+2+1,3+1+1+1.。2+2+1+1,2+1+1+1+1这些方案都由这句来分配。
以上是我个人理解,我觉得说的还挺详细的。看着书上这么混乱的讲解,我觉得讲解还算清楚。以下是源码:
#include <iostream>
using namespace std;
int divide(int ,int);
int main()
{
int n;
while( cin>>n )
{
cout<<divide(n,n)<<endl;
}
return 1;
}
int divide(int n,int m)
{
if( n<0 || m<0 ) return 0;
if( n==1 || m==1 ) return 1;
if( n==m )
return 1+divide(n,m-1);
else if( n<m )
return divide(n,n);
else
return divide(n-m,m)+divide(n,m-1);
}