递归---NYOJ-176 整数划分(二)和NYOJ-279队花的烦恼二

这道题目的递归思想和第一个题差不多, 主要思想是:func(n, m)的作用是将n划分为m个。

1. 如果n < m 的时候肯定是不能划分的,所以就返回0

2. 如果m = 1 或者 n = m 的时候,就一种划分方式

3. 如果n > m 的时候, 分为两种情况,一个是划分数中含有1, 一个是不含1, 所以含有1 的个数为func(n - 1, m - 1),意思就是从n去掉1,然后再划分m - 1个, 下面就是不含1的,

func(n - m, m), 这个式子的意思为, 先取出m个1来, 这样的话再将剩下的数,也就是n-m继续划分m个, 然后再把n - m个1加上去,肯定都是大于1的。所以式子为func(n - 1, m -1) + func(n - m, m);

代码如下(递归):

 1 #include <stdio.h>
 2 
 3 int func(int n, int m)
 4 {
 5     if(n < m)//n < m的时候肯定不能分, 所以返回0 
 6         return 0;
 7     if(m == 1 || n == m)
 8         return 1;
 9     else//此步是含1和不含1 
10         return func(n - 1, m - 1) + func(n - m, m);
11 }
12 int main()
13 {
14     int t, n, m;
15     scanf("%d", &t);
16     for(int i = 0; i < t; i++)
17     {
18         scanf("%d %d", &n, &m);
19         printf("%d\n", func(n, m));
20     }
21     
22     return 0;
23 }

 递推式已经出来了,所以可以用dp来做,其中数组dp[n][m]的值就代表n 划分 m 份时的数量, 也就是题目让求的拆分方法的数目,第一层for循环是从1-110个数的划分是多少,第二层是每个数的对应j个拆分方法的数目是多少, 所以最后找n 拆成m 个方法的数目就是dp[n][m];

代码如下(dp):

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 const int MAX = 110;
 5 int main()
 6 {
 7     int a[MAX][MAX];
 8     memset(a, 0, sizeof(a));
 9     a[1][1] = 1;
10     for(int i = 2; i < MAX; i++)
11     {
12         for(int j = 1; j <= i; j++)
13             a[i][j] = a[i - 1][j - 1] + a[i - j][j];
14     }
15     int t1, t2, t;
16     scanf("%d", &t);
17     while(t--)
18     {
19         scanf("%d %d", &t1, &t2);
20         printf("%d\n", a[t1][t2]);
21     }
22     return 0;
23 }

 题目279就不能用递归的方法来做了, 毕竟数据比这个大了,只能用第二种方法来做了。只要把第二种方法的MAX改一下就行了

posted @ 2014-10-30 16:59  Howe_Young  阅读(282)  评论(0编辑  收藏  举报