递归---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改一下就行了