1028:Ignatius and the Princess III

本题应该有两种方法:

1.母函数法

2.递推法

母函数不了解,待充分了解之后,再进行补充!

这里为递推实现的方法:

思路:

定义:n为要拆分的整数;

   k为拆分的项数;

   f[n][k]代表 n的整数拆分中,最大项不超过k的方案数。

  每一个整数n的拆分中,总有一项拆分为自己,即:n = n; 我们将其表示为f[n][1],而且f[n][1] = 1;

  又,每一个整数n的拆分中,总有一项拆分为n个1,即:n = 1 + 1 + ...... + 1(n个1的加和); 我们将其表示为f[0][0],且f[0][0] = 1;(注:n = 1时除外)。

所以:

  1 = 1;

  f[1][1] = 1;

  2 = 2;
  2 = 1 + 1;

  f[2][2] = f[0][0] + f[2][1] = 2;

  n = 3时,

  3 = 3;
  3 = 2 + 1;//3 = (1+ 1) + 1;
  3 = 1 + 1 + 1;

  f[3][1] = 1;

  f[3][2] = 拆分为两项的 数目 + 拆分为一项的 数目 = f[1][1] + f[3][1]; 之所以用f[1][1]在此表示,是因为分成两项时,以1+1作为基底数,然后向上加数,能加的数只有1,加到哪一项上都是一样的,所以就相当于f[1][1]的效果。

  同理,n = 4时,

  4 = 4;
  4 = 3 + 1;
  4 = 2 + 2;
  4 = 2 + 1 + 1;
  4 = 1 + 1 + 1 + 1;

  像:f[4][2] = f[2][2] + f[4][1];

  所以,结论就是:

  对于任意满足条件的拆分,最大项要么达到k这个限制,要么小于它,因此f(n, k) = f(n-k, k) + f(n, k - 1)。

  边界条件:f(n, 1) = 1, f(0, 0) = 1, f(1, 1) = 1, 另外,f(n, k) = f(n, n),如果k大于n的话。

实现代码:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 const int MAX = 125;
 5 int f[MAX][MAX] = {0};
 6 void Init()
 7 {
 8     f[0][0] = 1;
 9     for(int i = 1;i<MAX;i++)
10         f[i][1] = 1;
11     for(int n = 2;n<MAX;n++)
12     {
13         for(int k = 2;k<=n;k++)
14         {
15             int j;
16             if(n-k<k)
17                 j = n-k;
18             else
19                 j = k;
20             f[n][k] = f[n-k][j] + f[n][k-1];
21         }
22     }
23 }
24 int main()
25 {
26     Init();
27     int n;
28     while(cin>>n)
29     {
30         cout<<f[n][n]<<endl;
31     }
32     return 0;
33 }
View Code

  

 

原文地址:https://www.cnblogs.com/ttzm/p/6103880.html