先注明学习博客的地址:(http://www.cnblogs.com/hoodlum1980/archive/2008/10/11/1308493.html

题目描述:任何正整数n都可以写成n=n1+n2+n3+……+nk;1<=n1,n2,n3,……nk<=n;这被称为整数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的划分个数,6的划分个数为11。

该博主给出了两种做法,我先研究一下第一种做法(递归法)

首先引入另一个概念:n的m划分,就是说划分必须满足:1<=n1,n2,n3,……nk<=m;这时我们就可以进行递归的分析了,求n的划分就是求f(n,n);

下面讨论f(n,m)的求法:

1.当n等于1时,只有一种划分;

2.当m等于1时,也只有一种划分;

3.当n=m时,

划分中含有m时,有一种划分;

划分中不含m时,有f(n,m-1)中划分;

综上:f(n,m)=1+f(n,m-1);

4.当n>m时,

划分中含有m时,即划分的形式是{m,{x1, x2, ..., xi}},则{x1, x2, ..., xi}个数为f(n-m,m);

划分中不含m时,即划分中的数都比m小,则划分个数为f(n,m-1);

综上划分f(n,m) =  f(n-m,m)+f(n,m-1);

通过对求f(n,m)的过程分析,可见可能出现n<m的情况。

5.当n<m时,f(n,m)= f(n,n);

综上:

f(n, m) =             1;                                         ( n = 1 or m = 1 )

f(n, n);                                 ( n < m )

1+ f(n, m - 1);                      ( n = m )

f(n - m, m) + f(n, m - 1);       ( n > m )

在写代码AC掉那道题之前,先体会一下,这个递归为什么能成为递归的经典例题吧。其实这题并不能很明显的找到缩小问题规模的入口,反而让你引入了一个过渡的变量,而且每一步的缩小都很勉强,只能从表达式上看出来。我之所以觉得这道题很好的原因是因为这种分类讨论是高中时经常用的,或许这才是活学活用的实例,是一种考虑问题的方式,是一种生活的态度,是智商带动情商的提高(扯远了&……&……&)。

正经事AC代码:

  1. #include<stdio.h>
  2.  
  3. int F(int n, int m)
  4. {
  5. if (n == )
  6. return ;
  7. if (m == )
  8. return ;
  9. if (n < m)
  10. return F(n, n);
  11. if (n == m)
  12. return F(n, m - ) + ;
  13. if (n>m)
  14. return F(n - m,m) + F(n, m - );
  15. }
  16.  
  17. int main()
  18. {
  19. int T;
  20. scanf("%d",&T);
  21. while (T--)
  22. {
  23. int n;
  24. scanf("%d",&n);
  25. printf("%d\n",F(n,n));
  26. }
  27. }

这里其实还是有一个问题的就是是否有必要加上记忆化搜索,经过测试发现是很有必要加的,测试的代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3.  
  4. int a[][];
  5.  
  6. int F(int n, int m)
  7. {
  8. if (a[n][m] > ){
  9. printf("Ues the a[%d][%d]\n",n,m);
  10. return a[n][m];
  11. }
  12. if (n == )
  13. return a[][m]=;
  14. if (m == )
  15. return a[n][]=;
  16. if (n < m)
  17. return a[n][n]=F(n, n);
  18. if (n == m)
  19. return a[n][m]=F(n, m - ) + ;
  20. if (n>m)
  21. return a[n][m]=F(n - m,m) + F(n, m - );
  22. }
  23.  
  24. int main()
  25. {
  26. int T;
  27. scanf("%d",&T);
  28. while (T--)
  29. {
  30. memset(a,-,sizeof(a));
  31. int n;
  32. scanf("%d",&n);
  33. printf("%d\n",F(n,n));
  34. }
  35. }

好了,这题就到这儿了,至于博主提供了另一个方法,暂时就不讨论了。

整数划分——真正的递归经典例题(NYOJ——90)的更多相关文章

  1. NYOJ90 整数划分(经典递归和dp)

    整数划分 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,  其中n1≥n2≥…≥nk≥1,k≥1.  正 ...

  2. nyoj 90 整数划分

    点击打开链接 整数划分 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk,  其中n1≥n2≥-≥nk≥1,k≥ ...

  3. C语言经典例题100

    C语言经典例题100 来源 http://www.fishc.com 适合初学者 ----------------------------------------------------------- ...

  4. NYOJ-571 整数划分(三)

    此题是个非常经典的题目,这个题目包含了整数划分(一)和整数划分(二)的所有情形,而且还增加了其它的情形,主要是用递归或者说是递推式来解,只要找到了递推式剩下的任务就是找边界条件了,我觉得边界也是非常重 ...

  5. nyoj_90_整数划分_201403161553

    整数划分 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正整数 ...

  6. C语言中的经典例题用javascript怎么解?(一)

    C语言中的经典例题用javascript怎么解?(一) 一.1+2+3+……+100=?        <script type="text/javascript">  ...

  7. 整数划分 (区间DP)

    整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...

  8. 整数划分 Integer Partition(一)

    话说今天百度面试,可能是由于我表现的不太好,面试官显得有点不耐烦,说话的语气也很具有嘲讽的意思,搞得我有点不爽.Whatever,面试中有问到整数划分问题,回答这个问题过程中被面试官搞的不胜其烦,最后 ...

  9. POJ1664(整数划分)

    放苹果 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 30894   Accepted: 19504 Description ...

随机推荐

  1. kafka常用的shell命令

    kafka常用shell命令: ------------------------------------ 1.创建topic bin/kafka-topics.sh --create --zookee ...

  2. 算法(Algorithms)第4版 练习 1.3.42

    After copy Left on Stack r: be to not or be to Left on Stack copy: be to not or be to After r pop Le ...

  3. python第四篇:linux命令行总结 + 自动备份Python程序

    由于最近需要学习Python爬虫相关的知识,所以就先从Python基础.Linux基础开始进行了学习,下面主要是总结了常见的Linux的命令行.最后为了巩固学到的东西,尝试写了个自动备份的Python ...

  4. Codeforces 914C Travelling Salesman and Special Numbers:数位dp

    题目链接:http://codeforces.com/problemset/problem/914/C 题意: 对数字x进行一次操作,可以将数字x变为x在二进制下1的个数. 显然,一个正整数在进行了若 ...

  5. Codeforces 479E Riding in a Lift:前缀和/差分优化dp

    题目链接:http://codeforces.com/problemset/problem/479/E 题意: 有一栋n层的房子. 还有一个无聊的人在玩电梯,每次玩电梯都会从某一层坐到另外一层. 他初 ...

  6. 分享知识-快乐自己:FastDFS 上传 java 源码

    FastDFS 上传 java 源码:点我下载源码 首先导入 POM 文件:解决 maven 不能下载 fastdfs-client-java JAR <dependency> <g ...

  7. Web中常用字体介绍

    1.在Web编码中,CSS默认应用的Web字体是有限的,虽然在新版本的CSS3,我们可以通过新增的@font-face属性来引入特殊的浏览器加载字体. 浏览器中展示网页文字内容时,文字字体都会按照设计 ...

  8. Javascript-- jQuery事件篇(2)

    jQuery表单事件之blur与focus事件 单处理事件focusin事件与focusout事件,同样用于处理表单焦点的事件还有blur与focus事件 它们之间的本质区别: 是否支持冒泡处理 举个 ...

  9. Oracle忘记用户名密码

    一.oracle 11g登录服务开启 成功安装Oracle 11g后,共有7个服务,这七个服务的含义分别为:1. Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写 ...

  10. 关于自动化与vTable两种暴露接口的区别-1未完......

    COM组件有两种暴露组件接口的方式,一种是以虚拟列表的方式暴露:一种就是自动化方式. 虚拟列表(VTable): COM组件将自己所有的方法的地址以一个虚拟表的方式存放在一起,这个虚拟表是一种结构,有 ...