整数划分

思想

整数划分,是指把一个正整数n表示成系列正整数之和:
例如正整数6有如下11种不同的划分,所有p(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

我们假设函数f(n,m):
n为要整数划分的数,m为划分中出现的最大加数
然后可以推出递归关系(反正我是推不出,只能理解了 (●—●))
f ( 1 , m ) = 1 f(1,m)=1 f(1,m)=1 m ≥ 1 m\geq1 m1
n = 1 n=1 n=1时,不论m的值为多少( m > 0 m>0 m>0),只有一种划分即一个1。这很好理解,只要m选择比1大的数都会大于n。
f ( n , 1 ) = 1 f(n,1)=1 f(n,1)=1 n ≥ 1 n\geq1 n1
m = 1 m=1 m=1时,不论n的值为多少( m > 0 m>0 m>0),只有一种划分即n个1。这也好理解,最大的加数为1,只能n个1相加才能等于n。
f ( n , m ) = f ( n , n ) f(n,m)=f(n,n) f(n,m)=f(n,n) m ≥ n m\geq n mn
最大加数m是不能超过整数划分的n的,因此只能更改最大整数m为整数划分的n。例如: f ( 3 , 5 ) = f ( 3 , 3 ) f(3,5)=f(3,3) f(3,5)=f(3,3)
f ( n , n ) = 1 + f ( n , n − 1 ) f(n,n)=1+f(n,n-1) f(n,n)=1+f(n,n1)
正整数n的划分是由 s = n s=n s=n的划分和 s ≤ n − 1 s\leq n-1 sn1的划分构成的。例如: f ( 6 , 6 ) = 1 + f ( 6 , 5 ) f(6,6)=1+f(6,5) f(6,6)=1+f(6,5)
f ( n , m ) = f ( n , m − 1 ) + f ( n − m , m ) , n > m > 1 f(n,m)=f(n,m-1)+f(n-m,m),n>m>1 f(n,m)=f(n,m1)+f(nm,m),n>m>1
个人觉得这个是最难的,感觉不好理解。
其解释为正整数n的最大加数s( s < m ss<m,说白了就是在1到m之间选择个比m更小的正整数),是由 s = m s=m s=m的划分和 s ≤ m − 1 s\leq m-1 sm1的划分组成。
例如: f ( 6 , 4 ) = f ( 6 , 3 ) + f ( 2 , 4 ) = f ( 6 , 3 ) + f ( 2 , 2 ) f(6,4)=f(6,3)+f(2,4)=f(6,3)+f(2,2) f(6,4)=f(6,3)+f(2,4)=f(6,3)+f(2,2)

f ( 6 , 4 ) = 9 f(6,4)=9 f(6,4)=9 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7 f ( 2 , 2 ) = 2 f(2,2)=2 f(2,2)=2
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
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
4+2,4+1+1

个人认为这个例子对于理解很重要,首先我们可以看出 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7除了与 f ( 6 , 4 ) = 9 f(6,4)=9 f(6,4)=9少了4+24+1+1划分外,其他部分是一致的。而右侧的 f ( 2 , 2 ) = 2 f(2,2)=2 f(2,2)=2虽然并不真正包含加数4,但是 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7缺少的虽然包含整数4,但4不需要进行划分(划分部分已经就不含有4了),所以划分的整数2(即 n − m n-m nm),则2的划分次数和 f ( 6 , 3 ) = 7 f(6,3)=7 f(6,3)=7缺少的划分刚好相等。
此处我们只需要考虑次数,而不需考虑真正的划分加法序列,因此以总次数为中心。
综上递归方程为:
f ( n , m ) = { 1 n = 1 , m = 1 f ( n , n ) n < m 1 + f ( n , n − 1 ) n = m f ( n , m − 1 ) + f ( n − m , m ) n > m > 1 f(n,m)=\begin{cases} 1 & n = 1,m = 1 \\ f(n,n) & n < m \\ 1+f(n,n-1) & n = m \\ f(n,m-1)+f(n-m,m) & n > m > 1 \end{cases} f(n,m)=1f(n,n)1+f(n,n1)f(n,m1)+f(nm,m)n=1,m=1n<mn=mn>m>1

代码

#include
using namespace std; 

int split(int n,int m)
{
	if(n == 1 || m == 1) return 1;
	else if(n < m) return split(n,n);
	else if(n == m) return split(n,n-1) + 1;
	else return split(n,m-1)+split(n-m,m);
}

int main()
{
	int n;
	printf("输入划分数:");
	scanf("%d",&n);
	printf("整数划分为:%d\n",split(n,n));
	return 0;
}

输入

6

输出

11

总结

第一次看见整数划分是在《数据结构1800题》里面,其中算法大多苦涩难懂。看到这一题时是一个填空题,刚好都是递归方程的填空。之前没接触过,看着有些懵。在此看时才明白是怎么回事。
我相信学习是一个迭代的过程,只要不断进步不断努力就好!

你可能感兴趣的:(算法基础)