整数划分——真正的递归经典例题(NYOJ——90)
先注明学习博客的地址:(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代码:
#include<stdio.h> int F(int n, int m)
{
if (n == )
return ;
if (m == )
return ;
if (n < m)
return F(n, n);
if (n == m)
return F(n, m - ) + ;
if (n>m)
return F(n - m,m) + F(n, m - );
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int n;
scanf("%d",&n);
printf("%d\n",F(n,n));
}
}
这里其实还是有一个问题的就是是否有必要加上记忆化搜索,经过测试发现是很有必要加的,测试的代码:
#include<stdio.h>
#include<string.h> int a[][]; int F(int n, int m)
{
if (a[n][m] > ){
printf("Ues the a[%d][%d]\n",n,m);
return a[n][m];
}
if (n == )
return a[][m]=;
if (m == )
return a[n][]=;
if (n < m)
return a[n][n]=F(n, n);
if (n == m)
return a[n][m]=F(n, m - ) + ;
if (n>m)
return a[n][m]=F(n - m,m) + F(n, m - );
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(a,-,sizeof(a));
int n;
scanf("%d",&n);
printf("%d\n",F(n,n));
}
}
好了,这题就到这儿了,至于博主提供了另一个方法,暂时就不讨论了。
整数划分——真正的递归经典例题(NYOJ——90)的更多相关文章
- NYOJ90 整数划分(经典递归和dp)
整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正 ...
- nyoj 90 整数划分
点击打开链接 整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+-+nk, 其中n1≥n2≥-≥nk≥1,k≥ ...
- C语言经典例题100
C语言经典例题100 来源 http://www.fishc.com 适合初学者 ----------------------------------------------------------- ...
- NYOJ-571 整数划分(三)
此题是个非常经典的题目,这个题目包含了整数划分(一)和整数划分(二)的所有情形,而且还增加了其它的情形,主要是用递归或者说是递推式来解,只要找到了递推式剩下的任务就是找边界条件了,我觉得边界也是非常重 ...
- nyoj_90_整数划分_201403161553
整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正整数 ...
- C语言中的经典例题用javascript怎么解?(一)
C语言中的经典例题用javascript怎么解?(一) 一.1+2+3+……+100=? <script type="text/javascript"> ...
- 整数划分 (区间DP)
整数划分(四) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...
- 整数划分 Integer Partition(一)
话说今天百度面试,可能是由于我表现的不太好,面试官显得有点不耐烦,说话的语气也很具有嘲讽的意思,搞得我有点不爽.Whatever,面试中有问到整数划分问题,回答这个问题过程中被面试官搞的不胜其烦,最后 ...
- POJ1664(整数划分)
放苹果 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 30894 Accepted: 19504 Description ...
随机推荐
- FOJ 2213 简单几何
题意:给你两个圆的圆心坐标和半径,判断两个圆公切线数目. 思路:考虑两个圆间公切线的情况,两个圆的位置关系分为相离,相交,外切,内切,内含,重合,公切线数分别为4,2,3,1,0,-1. #inclu ...
- MHA高可用集群安装配置
4台服务器 192.168.136.128 主 192.168.136.129 从 192.168.136.130 从 192.168.136.131 管理服务器 一主2从,一管理,安装mysql并配 ...
- Codeforces Round #260 (Div. 2) A , B , C 标记,找规律 , dp
A. Laptops time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- Win7.窗口自动滚动回到屏幕
PS:笔记本 ThinkPad E440 1.前提:窗口 的一部分位于在屏幕的外面,此窗口处于激活的状态 操作:鼠标放置在窗口内部,鼠标继续往屏幕外部移动,鼠标没有任何其他事件(只有 MouseMov ...
- python第三篇:python、flask关系映射
python中关系映射主要包括三种:一对多关系映射.一对一关系映射.多对多关系映射. 一对多关系映射 一方:Student(学生) 添加关联属性和反向引用 多方:Article(文章) 添加外键关联 ...
- java:练习超市卖场
java:练习超市卖场 涉及到:大商品类,具体商品(以书为例),卖场类 Goods,Book,superMart, 商品类Goods: public interface Goods { //商品类 ...
- Python基础之列表操作
列表的常用操作包括但不限于以下操作: 列表的索引,切片,追加,删除,切片等 这里将对列表的内置操作方法进行总结归纳,重点是以示例的方式进行展示. 使用type获取创建对象的类 type(list) 使 ...
- PyCharm配置过程记录
也可以通过命令行来上传和下载git bash here 同步最新代码到本地: git fetch git pull 上传文件至git仓库: git commit git push 安装第三方模块方式 ...
- JavaUtil_07_HttpUtil_使用Hutool 封装的 HttpUtil
二.参考资料 1.[Hutool]Hutool工具类之Http工具——HttpUtil
- linux命令学习笔记(15):tail 命令
tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件, tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新 ...