递归---NYOJ-90整数划分(一)
2014-10-29 21:58
225 查看
这个题理解了好大会才理解,看了网上的代码,不太理解,但是后来看了好几个人的, 大同小异吧,慢慢的就理解了。
思路:
递归函数的意思是, 将 n 划分为最大数为 m 的划分数, 可以分几种情况
1. 当n = 1 的时候, 这时候就是将1划分, 也就是递归的出口, 1 肯定只能划分为 1, 所以返回1
2. 当m = 1的时候, 最大的数为1, 所以只能全划分为1才行, 所以就一种,return 1;
3. 当n < m的时候, 一个数肯定不能划分为比他要大的数, 最大只能划分到它本身,所以只需要将m变成n就行了,所以func(n, n);
4. 当n > m 时,根据划分中是否包含最大值 m,可以分为两种情况:
(a). 划分中包含 m 的情况,即 { m, { x1, x2, ..., xi } }, 其中 { x1, x2, ..., xi } 的和为 n - m,可能再次出现 m,因此是(n - m)的 m 划分,因此这种划分
个数为 f(n-m, m);
(b). 划分中不包含 m 的情况,则划分中所有值都比 m 小,即 n 的 ( m - 1 ) 划分,个数为 f(n, m - 1);
因此 f(n, m) = f(n - m, m) + f(n, m - 1);
5. 当 n = m 时,根据划分中是否包含 n,可以分为两种情况:
(a). 划分中包含n的情况,只有一个即 { n };
(b). 划分中不包含n的情况,这时划分中最大的数字也一定比 n 小,即 n 的所有 ( n - 1 ) 划分。
因此 f(n, n) = 1 + f(n, n-1);
大体思路就是这样,不理解的话可以尝试着代入数据试试,理解理解大体概念,下面是代码的实现:
方法一(递归版):
方法二(dp):
思路:
递归函数的意思是, 将 n 划分为最大数为 m 的划分数, 可以分几种情况
1. 当n = 1 的时候, 这时候就是将1划分, 也就是递归的出口, 1 肯定只能划分为 1, 所以返回1
2. 当m = 1的时候, 最大的数为1, 所以只能全划分为1才行, 所以就一种,return 1;
3. 当n < m的时候, 一个数肯定不能划分为比他要大的数, 最大只能划分到它本身,所以只需要将m变成n就行了,所以func(n, n);
4. 当n > m 时,根据划分中是否包含最大值 m,可以分为两种情况:
(a). 划分中包含 m 的情况,即 { m, { x1, x2, ..., xi } }, 其中 { x1, x2, ..., xi } 的和为 n - m,可能再次出现 m,因此是(n - m)的 m 划分,因此这种划分
个数为 f(n-m, m);
(b). 划分中不包含 m 的情况,则划分中所有值都比 m 小,即 n 的 ( m - 1 ) 划分,个数为 f(n, m - 1);
因此 f(n, m) = f(n - m, m) + f(n, m - 1);
5. 当 n = m 时,根据划分中是否包含 n,可以分为两种情况:
(a). 划分中包含n的情况,只有一个即 { n };
(b). 划分中不包含n的情况,这时划分中最大的数字也一定比 n 小,即 n 的所有 ( n - 1 ) 划分。
因此 f(n, n) = 1 + f(n, n-1);
大体思路就是这样,不理解的话可以尝试着代入数据试试,理解理解大体概念,下面是代码的实现:
方法一(递归版):
#include <stdio.h> int func(int n, int m)//func(n, m) 是将 n 划分为最大数不超过m的划分 { if(n == 1 || m == 1) return 1; if(n < m)//因为不可能将n划分成比n还大的数,所以,直接m = n就行了 return func(n, n); else if(n > m)/*当将n划分为比它小的数时, 一个是继续往下再找一个,还有一个就是剩下的那个*/ return func(n, m - 1) + func(n - m, m); else if(n == m)//n = m的时候, 也就是它的上一个的划分加上1 return 1 + func(n, m - 1); } int main() { int m; scanf("%d", &m); for(int i = 0; i < m; i++) { int n; scanf("%d", &n); printf("%d\n", func(n, n)); } return 0; }
方法二(dp):
//dp #include <stdio.h> const int MAX = 11; int main() { int dp[MAX + 1][MAX + 1]; for(int i = 1; i <= MAX; i++) dp[i][1] = dp[1][i] = 1;//初始化 for(int i = 2; i <= MAX; i++) { for(int j = 2; j <= MAX; j++) { if(i == j) dp[i][i] = dp[i][i - 1] + 1; else if(i < j) dp[i][j] = dp[i][i]; else dp[i][j] = dp[i][j - 1] + dp[i - j][j]; } } int m, t; scanf("%d", &m); for(int i = 0; i < m; i++) { scanf("%d", &t); printf("%d\n", dp[t][t]); } return 0; }
相关文章推荐
- nyoj 90 整数划分(一) (dp||递归)
- 整数划分——真正的递归经典例题(NYOJ——90)
- NYOJ90-整数划分,经典递归思想~~
- NYOJ90 整数划分(经典递归和dp)
- 【dp】NYOJ 90 整数划分
- NYOJ90-整数划分
- nyoj 571 整数划分(三)(递归)
- 整数划分 NYOJ 90
- NYOJ 279 队花的烦恼二和NYOJ 176 整数划分(二)【dp问题或递归】
- NYOJ90整数划分
- nyoj 571 整数划分(三)(递归)
- NYOJ 90 整数划分
- NYOJ 90 整数划分
- 整数划分 nyoj 90
- nyoj90整数划分
- nyoj90整数划分(dp)
- nyoj-90-整数划分
- nyoj 571 整数划分(三)(递归)
- nyoj 571 整数划分(三)(递归)
- NYOJ 90 整数划分