整数的划分问题

题目如下:

整数的分划问题。
如,对于正整数n=6,可以分划为:
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
现在的问题是,对于给定的正整数n,编写算法打印所有划分,并求出划分的总数。
用户从键盘输入 n (范围1~10)
程序输出该整数的所有划分。

注意,分划与顺序无关,例如5+1和1+5是同一种分划。另外,这个整数M本身也算
是一种分划。

解析:

该题中有两问:

1.求出划分的总数

  设PC(M)为整数M的所有划分总数,则:

  我们定义一个函数Partion(M,N),表示整数M的“任何被加数都不超过N”的分划的数目。
  Partion(M.N)有以下递归关系:
  1)Partion(M,1)=1,表示当最大的被加数是1时,该整数M只有一种分划,即M个1相加;
  2)Partion(1,N)=1,表示整数M=1只有一个分划,不管最大被加数的上限N是多大;
  3)Partion(M,N)=Partion(M,M),如果M<N。很明显,M的分划不可能包含大于M的被加数N;
  4)Partion(M,M)=1+Partion(M,M-1)。等式的右边分为两部分:第一部分的1表示M只包含一个被
  加数等于M本身的分划;第二部分表示M的所有其他分划的最大被加数N<=M-1,所以
  其他分划的数目就是等式右边的第二项。
  5)Partion(M,N)=Partion(M,N-1)+Partion(M-N,N),如果M>N。等式右边的第一部分表示被加数中不包
  含N的分划的数目;第二部分表示被加数中包含N的分划的数目,因为如果确定了一
  个分划的被加数中包含N,则剩下的部分可以按照对M-N的分划进行划分。
  上述五个递归关系式对Partion(M,N)作了递归定义。因为M的所有分划的数目PC(M)=Partion(M,
  M),所以上述关系式也定义了P(M)。

  C++实现代码如下:

Partion

2.求出具体的划分结果

  同样采用递归处理。借助一个长度为10的数组来存储中间值,len表示最大的那个数,相当于Partion(M,N)中的N,所有划分的数都不超过它。

View Code
PartionResult
 1 void PartionResult(int n, int m)
2 {
3 int i = 0;
4 if(n == 0)
5 {
6 cout << a[0];
7 for(i = 1; i < m; i++)
8 {
9 cout << " + " << a[i];
10 }
11 if( m > len)
12 {
13 cout << endl;
14 len++;
15 }
16 else
17 cout << ", ";
18 return;
19 }
20
21 for(i = n; i >= 1; i--)
22 {
23 if(m == 0 || i <= a[m - 1])
24 {
25 a[m] = i;
26 fun(n - i, m + 1);
27 }
28 }
29 }

 

注意:测试的时候最好用10以内的数字测试,因为划分的个数随划分数成指数增长。这里的存储中间值的数组只有10个字节。

你可能感兴趣的:(问题)