例一:整数划分问题
将正整数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)。
下面对可能出现的四种情况进行分析:
① m=1:
当m等于1时,对n的划分只可能1+1+1+……+1这一种情况。
②m>n时:
当m大于n时,由于划分中不可能出现负数,所以{n1, n2, n2,… , nk}(n = n1+n2+n3+……+nk)只可能出现小于等于n的整数。故有q(n, m)=q(n, n)
⑤m=n时:
当m等于n时,包含n自身的划分和没有n的划分两个部分。而包含n自身的划分只有一种情况,故有有q(n, n)=1+q(n,n-1)
④m<n时:
n的m划分有包含m和不包含m两个部分。其中包含m的部分用集合可表示为{m, {x1, x2, x3, 4,…, xk}}(其中x1+x2+……+xk=n-m)【详解见图1】,这部分的划分数为q(n-m, m);而不包含m的划分中,最大值不能为m,故划分数就等于q(n, m)。所以在m<n时整数n的划分数为:q(n, m)=q(n, m-1)+q(n-m, m)。
【图1:ipad坏了,一时找不到纸,后面再补吧。。】
递归求整数划分:
1 int q(int n, int m){ 2 if(m==1){ 3 return 1; 4 } 5 else if(m>n){ 6 return q(n,n); 7 } 8 else if(m==n){ 9 return q(n,n-1)+1; 10 } 11 else if(m<n){ 12 return q(n-m, m)+q(n,m-1); 13 } 14 }