【递归】 整数划分问题
资料主要来源于:
【计算机算法设计与分析(第五版)】【王晓东】【电子工业出版社】
例5 整数划分问题
将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。求正整数n的不同划分个数。
例如:正整数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。
一些经典的递归问题(阶乘,斐波那契),问题本身都具有比较明显的递归关系,因而容易用递归函数直接求解。
在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:将最大加数n1不大于m的划分个数记作q(n,m)。可以建立q(n,m)的如下递归关系。(若不理解加粗部分,建议把题目多读几遍)
(1) q(n,1)=1, n≥1; 当最大加数n1不大于1时,任何正整数n只有一种划分形式, 即n=1+1+…+1(n个1)
(2) q(n,m)=q(n,n), m ≥ n;
最大加数n1实际上不能大于n。因此,q(1,m)=1。
(3) q(n,n)=1+q(n,n-1);
正整数n的划分由n1=n的划分和n1 ≤ n-1的划分组成。
(4) q(n,m)=q(n,m-1)+q(n-m,m), n>m> 1;
正整数n的最大加数n1不大于m的划分,由n1≤ m-1 的划分和n1=m的划分组成。n1=m 的划分就是该划分中必然包含数m,因此其划分的数目与n-m的m划分一致。
如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:将最大加数n1不大于m的划分个数记作q(n,m)。可以建立q(n,m)的如下递归关系。(正整数n的划分数p(n)=q(n,n)。 )

q(n,m)=q(当前需要被划分的数字,划分中的加数的最大取值)
#include <iostream>
using namespace std;
int q(int n, int m)
{
if((n < 1) || (m < 1)) //无意义情况
return 0;
if((n == 1) || (m == 1))//数字1,划分最大加数为1的划分只会有1种
return 1;
if(n < m) //需要划分的数字n,实际情况不会小于其划分最大加数
return q(n, n);
if(n == m) //正整数n的划分由n1=n的划分和n1 ≤ n-1的划分组成。
return q(n, m - 1) + 1;
return q(n, m - 1) + q(n - m, m);//被划分数为n,最大划分加数为m的划分数目,等于,
// 被划分数为n最大加数为m-1的划分数目 + 被划分数为(n-m)最大加数为m的划分数目
}
int main()
{
int m = 6, n = 6;
for(int i=1;i<=6;i++)
{
cout <<" 数字为"<<n<<"时,最大划分加数上限为"<<i<<"时的划分情况有"<< q(n, i) <<"种"<< endl;
}
}