递推与递归练习题
递规与递推习题汇总
递规与递推习题汇总2.1 遍历问题我们都很熟悉二叉树的前序、中序、后序遍历,在数据结构中常提出这样的问题:已知一棵二叉树的前序和中序遍历,求它的后序遍历,相应的,已知一棵二叉树的后序遍历和中序遍历序列你也能求出它的前序遍历。
然而给定一棵二叉树的前序和后序遍历,你却不能确定其中序遍历序列,考虑如下图中的几棵二叉树:a a a a/ / \ \b b b b/ \ / \c c c c所有这些二叉树都有着相同的前序遍历和后序遍历,但中序遍历却不相同。
【输入】输A数据共两行,第一行表示该二叉树的前序遍历结果s1,第二行表示该二叉树的后序遍历结果s2。
【输出】输出可能的中序遍历序列的总数,结果不超过长整型数。
【样例】trave1.in trave1.outabc 4bca【算法分析】根据二叉树先序遍历和后序遍历的特点,可以知道,先序遍历的第一个结点是后序遍历的最后一个结点,对于中序遍历来说却是中间的一个结点,这里所说的中间也只是相对而言的中间。
如果一棵二叉树的根结点没有左子树,那么先序遍历的第一个结点也是中序遍历的第一个结点,如果一棵二叉树的根结点没有右子树,那么先序遍历的第一个结点是中序遍历的最后一个结点。
我们这里还认为就是中序遍历的中间结点,上面两种情况只是特殊的情况。
设二叉树的结点总数为n(对于输入的字符串来说是它的长度),对于先序遍历的结果,第一个结点为根结点,从第二个结点到最后一个结点分为n种情况:根结点的左子树结点个数为n-1,右子树结点的个数为0;根结点的左子树结点个数为n-2,右子树结点的个数为1;……根结点的左子树结点个数为n-i,右子树结点的个数为i-1;{0<=i<=n-1);……根结点的左子树结点个数为0,右子树结点的个数为n-1。
根据这n种情况,分别将二叉树拆分为左子树和右子树,左子树结点个数为n-i,右子树结点的个数为i-l(0<=i<=n-1),先序遍历的结果是从第二个结点(字符)开始取,而后序遍历的结果里是从第1个结点字符开始取。
关于递归与递推的那七道题
关于递归与递推的那七道题递归与递推是动态规划最底层的东西,掌握好它对于彻底的理解动规是至关重要的,这次做的题不难,但是它很能锻练人的思维,每一道题都有多种解法。
只要静下心来想,一般人都能做出来,而在做题的过程中,你会有很大的收获。
1、一只小蜜蜂...题目是这样的,有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。
请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。
对于这种题目,我们首先得找出蜂房之间的关系,如从1只能走到2和3,从2只能走到3和4,从3只能走到4和5……,因此我们可以得到它们的递推关系:f[a] = f[a+1]+f[a+2];下面我们再来找出口,把这个问题化简,即当a与b相邻时(a+1=b 或a+2=b),f[a] = 1,所以这个问题可以解决了。
它就是一个递归,遇到b就结束。
为了减少重复访问,我们可以用记忆化搜索来提高效率。
这个题也可以顺着来推,即从a到a有0条路线,从a到a+1有1条路线,从a 到a+2有1条路线,而a+3的路线条数来源于a+1和a+2的路径条数。
f[a] = 0;f[a+1] = 1;f[a+2] = 1;f[a+3] = f[a+1]+f[a+2];……f[b] = f[b-1]+f[b-2];由上面的式子就可以看出,它就是一个菲波拉契数列。
2、LELE的RPG难题题目描述:有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法.以上就是著名的RPG难题.解法一:这个题目经过同学们的讨论,得出了三种解法。
我所用的方法还是搜索,我们先不考虑它的限制条件,把第一个格子看成是树的根,那么总共可以建成三棵树,每一棵树的结点都有三个孩子。
我们的目标就是要统计这三棵树中分别从根结点走到叶子结点的总的路径条数。
然后把限制条件加上,把不符合要求的路径去掉,即可得出最终的结果。
关于递归的一些小练习
关于递归的⼀些⼩练习递归什么是递归在程序中, 所谓的递归, 就是函数⾃⼰直接或间接的调⽤⾃⼰.1. 直接调⽤⾃⼰2. 间接调⽤⾃⼰就递归⽽⾔最重要的就是跳出结构. 因为跳出了才可以有结果.所谓的递归就是化归思想递归的调⽤, 写递归函数, 最终还是要转换为⾃⼰这个函数.假如有⼀个函数 f, 如果它是递归函数的话, 那么也就是说函数体内的问题还是转换为 f 的形式.递归思想就是将⼀个问题转换为⼀个已解决的问题来实现function f() {... f( ... ) ...}例⼦: 1, 2, 3, 4, 5, ..., 1001. ⾸先假定递归函数已经写好, 假设是 foo. 即 foo( 100 ) 就是求 1 到 100 的和2. 寻找递推关系. 就是 n 与 n-1, 或 n-2 之间的关系: foo( n ) == n + foo( n - 1 )var res = foo( 100 );var res = foo( 99 ) + 100;3. 将递推结构转换为递归体function foo( n ) {return n + foo( n - 1 );}* 将求 100 转换为求 99* 将求 99 转换为求 98* ...* 将求 2 转换为求 1* 求 1 结果就是 1* 即: foo( 1 ) 是 14. 将临界条件加到递归体中function foo( n ) {if ( n == 1 ) return 1;return n + foo( n - 1 );}练习: 求 1, 3, 5, 7, 9, ... 第 n 项的结果与前 n 项和. 序号从 0 开始求第 n 项的1. ⾸先假定递归函数已经写好, 假设是 fn. 那么第 n 项就是 fn( n )2. 找递推关系: fn( n ) == f( n - 1 ) + 23. 递归体function fn( n ) {return fn( n-1 ) + 2;}4. 找临界条件求 n -> n-1求 n-1 -> n-2...求 1 -> 0求第 0 项, 就是 15. 加⼊临界条件function fn( n ) {if ( n == 0 ) return 1;return fn( n-1 ) + 2;}前n项和1. 假设已完成, sum( n ) 就是前 n 项和2. 找递推关系: 前 n 项和等于第 n 项 + 前 n-1 项的和3. 得到递归体function sum( n ) {return fn( n ) + sum( n - 1 );}4. 找临界条件n == 1 结果为 15. 得到递归函数function sum( n ) {if ( n == 0 ) return 1;return fn( n ) + sum( n - 1 );}练习: 2, 4, 6, 8, 10 第 n 项与前 n 项和第n项function fn( n ) {if ( n == 0 ) return 2;return fn( n-1 ) + 2;}前n项和function sum( n ) {if ( n == 0 ) return 2;return sum( n - 1 ) + fn( n );}练习: 数列: 1, 1, 2, 4, 7, 11, 16, … 求第 n 项, 求前 n 项和.求第 n 项1. 假设已经得到结果 fn, fn( 10 ) 就是第 10 项2. 找递推关系0, 1 => fn( 0 ) + 0 = fn( 1 )1, 2 => fn( 1 ) + 1 = fn( 2 )2, 3 => fn( 2 ) + 2 = fn( 3 )...n-1, n => fn( n-1 ) + n - 1 = fn( n )3. 递归体也就清楚了, 临界条件是 n == 0 => 1function fn( n ) {if ( n == 0 ) return 1;return fn( n-1 ) + n - 1;}如果从 1 开始表⽰, 那么第 n 项为1. 假设已经得到结果 fn, fn( 10 ) 就是第 10 项2. 找递推关系1, 2 => fn( 1 ) + 0 = fn( 2 )2, 3 => fn( 2 ) + 1 = fn( 3 )3, 4 => fn( 3 ) + 2 = fn( 4 )...n-1, n => fn( n-1 ) + n - 2 = fn( n )3. 临界条件 n == 1 => 1前n项和function sum( n ) {if ( n == 0 ) return 1;return sum( n - 1 ) + fn( n );}如果从 0 开始0 1 2 3 4 5 61, 1, 2, 4, 7, 11, 16,如果从 1 开始1 2 3 4 5 6 71, 1, 2, 4, 7, 11, 16,练习: Fibonacci 数列: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …求其第 n 项.递推关系 fn(n) == fn( n- 1) + fn( n - 2)function fib( n ) {if ( n == 0 || n == 1 ) return 1;return fib( n - 1 ) + fib( n - 2 );}阶乘阶乘是⼀个运算, ⼀个数字的阶乘表⽰的是从 1 开始累乘到这个数字. 例如 3! 表⽰1 * 2 * 3. 5! 就是1 * 2 * 3 * 4 * 5. 规定 0 没有阶乘, 阶乘从 1 开始.求 n 的阶乘function foo ( n ) {if ( n == 1 ) return 1;return foo( n - 1 ) * n;}求幂求幂就是求某⼀个数⼏次⽅2*2 2 的平⽅, 2 的 2 次⽅求 n 的 m 次⽅最终要得到⼀个函数 power( n, m )n 的 m 次⽅就是 m 个 n 相乘即 n 乘以 (m-1) 个 n 相乘function power ( n, m ) {if ( m == 1 ) return n;return power( n, m - 1 ) * n;}深拷贝如果要实现深拷贝那么就需要考虑将对象的属性, 与属性的属性, ... 都拷贝过来如果要实现:1. 假设已经实现 clone( o1, o2 ), 将对象 o2 的成员拷贝⼀份交给 o12. 简单的算法, 将 o2 的属性拷贝到 o1 中去function clone( o1, o2 ) {for ( var k in o2 ) {o1[ k ] = o2[ k ];}}3. 找递推关系, 或叫划归为已经解决的问题假设⽅法已经实现, 问⼀下, 如果 o2[ k ] 是对象继续使⽤这个⽅法因此需要考虑的是 o2[ k ] 如果是引⽤类型, 再使⽤⼀次 clone() 函数如果 o2[ k ]不是引⽤类型, 那么就直接赋值function clone( o1, o2 ) {for ( var k in o2 ) {if ( typeof o2[ k ] == 'object' ) {o1[ k ] = {};clone( o1[ k ] , o2[ k ] );} else {o1[ k ] = o2[ k ];}}}复杂实现: clone( o ) -> newObjfunction clone( o ) {var temp = {};for ( var k in o ) {if ( typeof o[ k ] == 'object' ) {temp[ k ] = clone( o[ k ] );} else {temp[ k ] = o[ k ];}}return temp;}请⽤递归实现 getElementsByClassName<div><div>1<div class="c">2</div><div>3</div></div><div class="c">4</div><div>5<div>6</div><div class="c">7</div></div><div>8</div></div>1. 如果实现⼀个⽅法 byClass( node, 'c', list ), 表⽰在某⼀个节点上查找符合 class 属性为 c 的元素2. 在当前元素的⼦元素中查找, 如果有符合要求的, 存储到⼀个数组中3. ⾸先遍历⼦节点, 然后看⼦节点是否还有⼦节点, 如果没有直接判断, 如果有再递归function byClass( node, className, list ) {var arr = node.childNodes;for ( var i = 0; i < arr.length; i++ ) {if ( arr[ i ].className == className ) {list.push( arr[ i ] );}if ( arr[ i ].childNodes.length > 0 ) {byClass( arr[ i ], className, list );}}}。
递归递推区别分析与例题总结
递归递推区别分析与例题总结递归与递推⽂章⽬录特点递归(recursive)运⾏过程中⾃我调⽤,求解过程分为回溯和递推两个过程,占⽤内存多(栈数先积累后收缩,有可能爆栈),代码简洁但低效。
尾递归和递归区别⬇function story() {从前有座⼭,⼭上有座庙,庙⾥有个⽼和尚,⼀天⽼和尚对⼩和尚讲故事:story() // 尾递归,进⼊下⼀个函数不再需要上⼀个函数的环境了,得出结果以后直接返回。
}function story() {从前有座⼭,⼭上有座庙,庙⾥有个⽼和尚,⼀天⽼和尚对⼩和尚讲故事:story(),⼩和尚听了,找了块⾖腐撞死了 // ⾮尾递归,下⼀个函数结束以后此函数还有后续,所以必须保存本⾝的环境以供处理返回值。
}尾递归省内存、⾼效(相当于(或者说递推?))Python⽆法在语⾔中实现尾递归优化(Tail Call Optimization, TCO),所以采⽤了for, while等特殊结构代替recursive的表述(优化是编译器⼲的,发现尾递归结构就给优化了)。
递推(iterative)效率⽐递归⾼,尽量递推,除⾮只能递归。
例题递推例⼦⼀般都是数学题。
重点是找递推公式(也太好偷懒了吧)平⾯分割问题直线分割平⾯(基本结论)如果当前有 n 条直线,新增加⼀条直线(第 n+1 条直线),可以多出来 n 个交点(新的直线和之前所有的直线都有交点),⽽多出来 n 个交点对应到可以多出 n+1 个平⾯(⽐如从两条线,⼜新增⼀条线时,新的线和两条线都相交,作⽤在三个区域上,对这三个区域切分,增加三个平⾯)。
也即:S n+1=S n+(n+1)=1+(n+1)(n+2)2当平⾯上已有n-1条曲线将平⾯分割成a n-1个区域后,第n-1条曲线每与曲线相交⼀次,就会增加⼀个区域,因为平⾯上已有了n-1条封闭曲线,且第n条曲线与已有的每⼀条闭曲线恰好相交于两点,且不会与任两条曲线交于同⼀点,故平⾯上⼀共增加2(n-1)个区域,加上已有的a n-1个区域,⼀共有a n-1+2(n-1)个区域。
递推与递归练习题
}
getch();
}
3.#include <stdio.h>
#include <stdlib.h>
#define N 30
void main()
{
int n, si,si1;
si1=1;
for(n=N-1;n>=1;n--)//倒数第二天开始
{
si=(si1+1)*2; //算出当天的桃子数
{
if(Duhe(a,b+2,0)==1)
return 1;
}
if(judge(a+2,b,1-a,3-b,0))
{
if(Duhe(a+2,b,0)==1)
return 1;
}
if(judge(a+1,b,2-a,3-b,0))
{
if(Duhe(a+1,b,0)==1)
return 1;
}
if(judge(a,b+1,3-a,2-b,0))
{ /*则判断下一个状态,直至问题解决*/
if(a==0&&b==0) return 1;
if(n==0) /*判断0状态时,商匪状态是否符合要求*/
{
if(judge(a-1,b-1,4-a,4-b,1))
{
if(Duhe(a-1,b-1,1)==1)
return 1;
}
if(judge(a,b-2,3-a,5-b,1))
2.(用递归做)商人渡河问题是这样的:有三个商人,三个强盗,和一条船(船每次只可以载小于等于两个人)他们同在河的一边,想渡过河去,但是必须保证在河的任何一边必须保证商人的数目大于等于强盗的数目,应该怎么过这条河呢?
递归递推测试题分析讲解
3
实现中常见的问题
问题一: 问题一: 不适应递归的思路,直接分析输入的字符串, 不适应递归的思路,直接分析输入的字符串,试图自 己写进栈出栈的程序,写得逻辑复杂, 己写进栈出栈的程序,写得逻辑复杂,因考虑不周出 错。 问题二: 问题二: 不会使用atof()函数,自己处理浮点数的读入, 不会使用atof()函数,自己处理浮点数的读入,逻 atof()函数 辑复杂出错。 辑复杂出错。
10
#include <stdio.h> int W,H; char z[21][21]; int f(int x,int y){ if(x<0||x>=W)||y<0||y>=H) return 0; if(z[x][y]==‘#’) return 0; else { z[x][y]=‘#’;//将走过的瓷砖做标记 z[x][y]=‘#’;//将走过的瓷砖做标记 return 1+f(x-1,y)+f(x+1,y)+f(x,y-1)+f(x,y+1) } } void main() { int i,j,num; while(scanf(“%d%d”,&H,&W) && W!=0 && H!=0){ num=0; for(i=0;i<W;i++) scanf(“%s”,z[i]); for(i=0;i<W;i++) for(j=0;j<H;j++) if(z[i][j]==‘’@)printf(“%d\n”,f(i,j)); } }
#include <stdio.h> int count(int x,int y){ if (y==1||x==0)return 1; if (x<y) return count(x,x); return count(x,y-1)+count(x-y,y); count(x,y-1)+count(x} void main() { int t,m,n; scanf(“%d”,&t); for (int i=0;i<t;i++){ scanf(“%d%d”,&m,&n); printf(“%d\ printf(“%d\n”,count(m,n)); }
递推习题——精选推荐
1、走楼梯【问题描述】楼梯有n级台阶,上楼可以一步上一个台阶,也可以一步上两个台阶。
编写一个递归程序,计算共有多少种不同的走法?【输入样例】3【输出样例】32、兔子繁殖【问题描述】有一种兔子,出生后一个月就可以长大,然后再过一个月一对长大的肚子就可以生育一对小兔子且以后每个月都能生育一对。
现在,我们有一对刚出生的这种兔子,那么,n个月后,我们会有多少对兔子呢?假设所有的兔子都不会死亡。
【输入格式】仅一行,包含一个自然数n。
【输出格式】仅一行,包含一个自然数,即n个月后兔子的对数。
【输入样例】5【输出样例】53、平面切割【问题描述】同一个平面内有n(n≤500)条直线,已知其中p(p≥2)条直线相交于同一点,则这n条直线最多能将平面分割成多少个不同的区域?【输入格式】两个整数n(n n≤500)和p(2≤p≤n)。
【输出格式】一个正整数,代表最多分割成的区域数目。
【输入样例】12 5【输出样例】734、蜜蜂路线【问题描述】一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房m开始爬到蜂房n,m<n,有多少种爬行路线?【输入格式】仅一行,包含两个自然数m,n。
【输出格式】仅一行,包含一个自然数,即爬行路线的种数。
【输入样例】1 14【输出样例】3775、数塔问题【问题描述】设有一个三角形的数塔,顶点为根结点,每个结点有一个整数值。
从顶点除法,可以向左下走或向右下走,如图所示:若要求从根结点开始,找出一条路径,使路径之和最大,只要输出路径之和的最大值。
【输入格式】第一行为n(n<10),表示数塔的层数。
第二行到n+1行,每行有若干个数据,表示数塔中的数值。
【输出格式】一个数据,即路径之和的最大值。
【输入样例】51311 812 7 266 14 15 812 7 13 24 11【输出样例】866、贮油点【问题描述】一辆重型卡车欲穿过1000公里的沙漠,卡车耗油为1升/公里,卡车总载油能力为500公升。
递归与递推
递推与递归练习题1、过河卒(NOIP2002普及组第4题)【问题描述】棋盘上A点有一个过河卒,需要走到目标B点。
卒行走的规则:可以向下、或者向右。
同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。
因此称之为“马拦过河卒”。
棋盘用坐标表示,A点(0, 0)、B点(n, m)(n, m为不超过15的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从A点能够到达B 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入:一行四个数据,分别表示B点坐标和马的坐标。
输出:一个数据,表示所有的路径条数。
【样例输入】knight.in6 6 3 3【样例输出】knight.out6【问题分析】跳马是一道老得不能再老的题目,每位编程者都学过,一般是在学习回溯或搜索算法时,很多书上也有类似的题目,一些比赛中也经常出现这一问题的变形(如NOIP1997初中组第三题)。
有些同学一看到这种类型的题目就去盲目搜索,但事实证明:当n,m=15就会超时。
其实,对本题稍加分析就能发现,到达棋盘上的一个点,只能从左边过来(我们称之为左点)或是从上面过来(我们称之为上点)。
根据加法原理,到达某一点的路径条数,就等于到达其相邻的上点或左点的路径数目总和。
因此我们可以使用逐列(逐行)递推的方法来求出从起点到终点的路径数目。
障碍点(马的控制点)也完全适用,只要将到达该点的路径数目设置为0即可。
假设用F[I,J]到达点(I,J)的路径数目用G[I,J]表示点(I,J)是否为对方马的控制点,G[I,J]=0表示不是对放马的控制点,G[I,J]=1表示是对方马的控制点。
则,我们可以得到如下的递推关系式:F[I,J]=0 {G[I,J]=1}F[I,0]=F[I-1,0] {I>0,G[I,0]=0}F[0,J]=F[0,J-1] {J>0,G[0,J]=0}F[I,J]=F[I-1,J]+F[I,J-1] {I>0,J>0,G[I,J]=0}上述递推式边界是:F[0,0]:=1。
递推—递归算法练习2
有了棋格的状态图后,程序应能判断让谁 先走,计算机选择必胜策略或双方和(双方均 不能到达目标格)的策略下棋,这样就能保证 计算机尽可能不败。
设 1 表示必胜态, -1 表示必败态, 0 表示和 态或表示无法到达的棋格。 例如,设N=10,S={1,2},则可确定其每个棋 格的状态如下所示:
1 -1 -1 1 -1 -1 1 -1 -1 1
而N=10,S={2,3}时,其每格的状态将会如下 所示:
0 -1 -1 0 1 0 -1 -1 0 1
二、钢板分割问题
问题:设有一块正方形的钢板,现需将它分成n个小 正方形。例如,当: n=2 不可能有解。 n=3 不可能有解。 n=4 可分成4个小正方形钢板。 n=5 不可能有解。 n=6 即一个大的加五个小的。 n=7 即三个较大的加四个小的。 n=8 即一个大的加七个小的。 问题:任给n,求出分成n个小正方形的方法。
三、剔除多余括号
键盘输入一个含有括号的四则运算表达式,可能 含有多余的括号,编程整理该表达式,去掉所有多 余括号,原表达式中所有变量和运算符相对位置保 持不变,并保持原表达式等价。 例如,处理表达式‘((a+b)*f)-(i/j)’,结果:‘(a+b)*f-i/j’。 分析: 首先考虑人处理这个问题的方法,就是依靠符 号来判断是否可以去括号。括号的前后,以及括号 内的符号,都需要考虑。因此,可以按照人的处理 方法,从最外层处理起,一层一层的去掉括号,这 便是分治的思想。而由于每次分治的处理过程基本 相同,用递归最为合适。
四、递推的应用(博弈问题)
走直线棋。有如下所示的一个编号为1到n的方格:
1 2 3 4 5 … … N-1 N
现由计算机和人进行人机对奕,从1到n,每次可以 走k个方格,其中k为集s={a1,a2, a3,....am}中的元 素(m<=4),规定谁最先走到第n格为胜,试设计一 个人机对奕方案,摸拟整个游戏过程的情况并力求 计算机尽量不败。
递归练习题(打印版)
递归练习题(打印版)### 递归练习题(打印版)#### 一、递归基础概念题1. 定义题:请简述什么是递归,并给出递归的基本形式。
2. 判断题:以下哪些函数是递归的?- A. `f(x) = x + 1`- B. `g(n) = n * g(n-1)` (n > 0)- C. `h(x) = x * h(x-1)` (x > 1)3. 简答题:递归和迭代有什么区别?#### 二、递归函数编写题1. 编写递归函数:编写一个递归函数,实现阶乘计算。
2. 编写递归函数:编写一个递归函数,实现斐波那契数列的第n项。
3. 编写递归函数:编写一个递归函数,实现汉诺塔问题的解决方案。
#### 三、递归算法应用题1. 应用题:如何使用递归算法解决归并排序问题?2. 应用题:使用递归算法解决二叉树的深度优先搜索(DFS)。
3. 应用题:描述如何使用递归算法实现图的深度优先搜索(DFS)。
#### 四、递归优化题1. 优化题:对于递归算法,如何避免重复计算?2. 优化题:请解释尾递归优化的概念,并给出一个尾递归的例子。
3. 优化题:如何使用记忆化递归(Memoization)来优化递归算法?#### 五、递归问题解决题1. 问题解决题:给定一个数字n,请使用递归算法找出n的二进制表示中1的个数。
2. 问题解决题:使用递归算法实现一个函数,判断一个字符串是否是回文。
3. 问题解决题:给定一个整数数组,使用递归算法找出数组中的最大值。
#### 六、递归思维拓展题1. 思维拓展题:递归算法在解决哪些类型的问题时特别有效?2. 思维拓展题:在编程中,递归算法有哪些潜在的缺点?3. 思维拓展题:请讨论递归算法在人工智能领域的应用。
#### 七、递归实践题1. 实践题:实现一个递归函数,用于计算组合数C(n, k)。
2. 实践题:编写一个递归函数,实现快速排序算法。
3. 实践题:给定一个字符串,使用递归算法实现字符串的反转。
《算法设计与分析》递归算法典型例题
算法递归典型例题实验一:递归策略运用练习三、实验项目1.运用递归策略设计算法实现下述题目的求解过程。
题目列表如下:(1)运动会开了N天,一共发出金牌M枚。
第一天发金牌1枚加剩下的七分之一枚,第二天发金牌2枚加剩下的七分之一枚,第3天发金牌3枚加剩下的七分之一枚,以后每天都照此办理。
到了第N天刚好还有金牌N枚,到此金牌全部发完。
编程求N和M。
(2)国王分财产。
某国王临终前给儿子们分财产。
他把财产分为若干份,然后给第一个儿子一份,再加上剩余财产的1/10;给第二个儿子两份,再加上剩余财产的1/10;……;给第i 个儿子i份,再加上剩余财产的1/10。
每个儿子都窃窃自喜。
以为得到了父王的偏爱,孰不知国王是“一碗水端平”的。
请用程序回答,老国王共有几个儿子?财产共分成了多少份?源程序:(3)出售金鱼问题:第一次卖出全部金鱼的一半加二分之一条金鱼;第二次卖出乘余金鱼的三分之一加三分之一条金鱼;第三次卖出剩余金鱼的四分之一加四分之一条金鱼;第四次卖出剩余金鱼的五分之一加五分之一条金鱼;现在还剩下11条金鱼,在出售金鱼时不能把金鱼切开或者有任何破损的。
问这鱼缸里原有多少条金鱼?(4)某路公共汽车,总共有八站,从一号站发轩时车上已有n位乘客,到了第二站先下一半乘客,再上来了六位乘客;到了第三站也先下一半乘客,再上来了五位乘客,以后每到一站都先下车上已有的一半乘客,再上来了乘客比前一站少一个……,到了终点站车上还有乘客六人,问发车时车上的乘客有多少?(5)猴子吃桃。
有一群猴子摘来了一批桃子,猴王规定每天只准吃一半加一只(即第二天吃剩下的一半加一只,以此类推),第九天正好吃完,问猴子们摘来了多少桃子?(6)小华读书。
第一天读了全书的一半加二页,第二天读了剩下的一半加二页,以后天天如此……,第六天读完了最后的三页,问全书有多少页?(7)日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。
小学计数知识学习习题:递推法(含答案)
小学计数知识学习:递推法习题一1.某数加7,乘以5,再减去9,得51.这个数是 .2.篮中有许多李子,如果将其中的一半又1个给第一个人,将余下的一半又2个给第二个人,然后将剩下的一半又3个给第三个人,篮中刚好一个也不剩,篮中原来有个李.3.一个箱子里放着一些茶杯,几个小朋友从箱里往外拿茶杯,规则是每次总要拿出箱里的一半,然后又放回一个.按这样规则他拿了597次后,箱里剩2个杯,他原有个杯.4.蜗牛沿着10M高的柱子往上爬,每天从清晨到傍晚向上共爬5M,夜间下滑4M,像这样,从某天清晨开始,它天才能爬上柱的顶端.5.小明在一次数学考试时,把一个数除以3.75计算成乘以3.75,结果得337.5.那么,这题的正确结果是 .1. (51+9)÷5-7=52. 最后剩下的一半:0+3=3(个)。
第二次余下的:3×2=6(个)。
第一次余下的一半:6+2=8(个)。
第一次余下的:8×2=16(个)。
篮中数的一半:16+1=17(个)。
篮中原有:17×2=34(个).3. 2个.(不管怎样拿多少次)4. 6天.只要前5M爬到即可,最后一天爬上5M.(10-5)÷(5-4)=5(天)5+1=6(天)5. 24.337.5÷3.73÷3.75=24.小学计数知识学习:递推法习题二1.一个数扩大3倍,再增加70,然后减少50,得80.这个数是 .2.学生问陈老师今年几岁,他笑着说:“把我的年龄减去4后,被7除,加上6后乘以5,刚好是半百,”那么陈老师今年岁.3.冰柜里的鸡蛋,第一天拿走了一半多两个,第二天拿走了余下的一半多4个,这时刚好拿完,求原来有个.4.在做一道加法题时,小马虎把个位上的5看作3,把十位上的6看成了9,得出结果是210,正确的结果是 .5.一捆电线,第一次用去全长一半多3M,第二次用去余下的一半少10M,第三次用去15M,最后还剩7M,这捆电线原来总长 M.1、20.[(80+50)-70]÷3=202、(50÷5-6)×7+4=32(岁)3、(2+4×2)×2=20(个)4、182.210-30+2=1825、54M.15+8-10=12(M)12×2=24(M)全半:24+3=27(M)全长:27×2=54(M)小学计数知识学习:递推法习题三1.有26块砖,兄弟俩拿去挑,弟弟抢在前,刚摆好姿势,哥哥赶到了.哥哥看到弟弟挑得太多,从弟弟那里抢过了一半,弟弟不服,又从哥哥那里抢回一半,哥哥不肯,弟弟只好给哥哥5块,此时哥哥比弟弟多挑2块,问最初弟弟准备挑多少块?2.批发站有若干筐苹果,第一天卖出一半,第二天运进450筐,第三天又卖出现有苹果的一半又50筐,还剩600筐,这个批发站原有多少筐.3.三人共有糖72粒,若甲给乙、丙各一些,使他们增加1倍.接着乙又给甲、丙各一些,使它们翻倍.最后丙也给甲、乙各一些,使他们翻倍.这时三人糖数相等,求三人原来各几粒?4.袋子里有若干个球,小明每次拿出其中的一半,再放回一个,一共做了5次,袋中还有3个球,问原来袋中有几个球?1. 16块12+5=17(块)(26-17)×2=18(块)(26-18)×2=16(块)2. 1700筐[(600+50)×2-450]×2=1700(筐)3. 甲:39。
递归与递推练习
递规与递推练习杨辉三角形(Triangle)【程序名称】triangle.exe【源程序名】triangle.(pas/c/cpp)【输入文件】triangle.in【输出文件】triangle.out【问题描述】有一个数字三角是我国古代著名数学家杨辉首先提出的,这个数字三角如下图所示:11 11 2 11 3 3 11 4 6 4 1……现在给你一个正整数n,请你用递归算法给出杨辉的前n行。
【输入数据】输入文件共一行,包含一个正整数n(1≤n≤20)。
【输出数据】输出文件共n行,即杨辉三角的前n行。
每行包含若干正整数,这些正整数之间用一个空格隔开(不能有多余的空格),最后一个正整数后面没有空格。
【样例】triangle.in4triangle.out11 11 2 11 3 3 1多米诺骨牌(Domino)【程序名称】domino.exe【源程序名】domino.(pas/c/cpp)【输入文件】domino.in【输出文件】domino.out【问题描述】有N块1×2大小的骨牌需要放入一个2×N的牌盒中,请问共有多少种放法(输出总放法数的最后100位即可)。
【输入数据】输入数据仅一个自然数N(N≤106)。
【输出数据】输出数据共4行,每行25位,共100位。
表示总放法数的最后100位。
不满100位时高位用0补足。
【样例】domino.in5domino.out0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008走楼梯(Stairs)【程序名称】stairs.exe【源程序名】stairs.(pas/c/cpp)【输入文件】stairs.in【输出文件】stairs.out【问题描述】有一楼梯共N阶,由于年久失修,其中有K阶台阶已经损坏(人不能在损坏的台阶上停留),已知某人一次能上一阶、两阶或三阶台阶,请问,此人从楼梯底部走到楼梯顶部,共有多少种走法。
递推递推-解递推数列问题渔夫分鱼A,B,C,D,E五个渔夫夜间合伙捕..
递推递推-解递推数列问题渔夫分鱼A,B,C,D,E五个渔夫夜间合伙捕鱼,凌晨都疲惫不堪,各自在草丛中熟睡。
第二天清晨A先醒来,他把鱼均分五份,把多余的一条扔回湖中,便拿了自己的一份回家了,B醒来后,也把鱼均分五份,把多余的一条扔回湖中,便拿了自己的一份回家了,C,D,E也按同样方法分鱼。
问5人至少捕到多少条鱼?使用数组分别存储五个人捕到的鱼吉普车穿越沙漠问题一、问题一辆吉普车来到1000km宽的沙漠边沿。
吉普车的耗油量为1L/km,总装油量为500L。
显然,吉普车必须用自身油箱中的油在沙漠中设几个临时加油点,否则是通不过沙漠的。
假设在沙漠边沿有充足的汽油可供使用,那么吉普车应在哪些地方、建多大的临的加油点,才能以最少的油耗穿过这块沙漠?二、问题分析本题是一个极值问题,要求具有最小的油耗。
因此,它的解是唯一的。
吉普车在沙漠中建临时油库,是逐步向前推进的,即建好一个油库后,再建下一个油库。
为使油耗最小应做到:(1)每次吉普车出发时都应满载,放下一部分油再返回时,油恰好用完,并且把下一个油库建好后这个油库中的油恰好用完。
所以每个点的油库中的油都应是吉普车装油量的整数倍(因为出发时满载),即500Xk(k为正整数),并且每个点的存油量为下一个点的存油量及吉普车为建立下个油库在两点之间往返的油耗之和(下一个油库建成,前一个油库中的油恰好用完)。
(2)吉普车为建立下一个油库运油次数应最少。
用递推法解这个题,可由一个点的存油量推出相邻的另一个点的存油量及两点之间的距离。
但正推是不可能的,因为第一个点的存油量及其距A的距离尚无法确定。
但是可推得最后一个点Cl的存油量应为500L,它与B相距为500km,这样吉普车从Cl到达B 恰好跑一趟B。
递推必须由已知的初始条件开始。
为此本题应使用倒推法。
图2-7为这一倒推过程的示意图。
图中A为起始点,B为终点,C1,C1,…,Cn分别为倒数第1,2,…,n个临时油库点。
由于B点无需储油,吉普车只须从Cl到达B即可,所以C1点的存油量应为500L,C1到B的距离为500km。
递推和递归作业
题1:编码(encode.???)【问题描述】编码工作常被运用于密文或压缩传输。
这里我们用一种最简单的编码方式进行编码:把一些有规律的单词编成数字。
字母表中共有26个字母{a,b,……,z},这些特殊的单词长度不超过6且字母按升序排列。
把所有这样的单词放在一起,按字典顺序排列,一个单词的编码就对应着它在字典中的位置。
例如:a --> 1b --> 2z --> 26ab --> 27ac --> 28你的任务就是对于所给的单词,求出它的编码。
【输入格式】仅一行,被编码的单词。
【输出格式】仅一行,对应的编码。
如果单词不在字母表中,输出0。
【输入样例】ab【输出样例】27题2:特殊的子集(subset.???)【问题描述】集合M={1,2,3,……n}的子集中,有一些是不含相邻自然数元素的。
例如:n=4时,集合{1,3}是满足要求的,而{1,3,4}是不满足的,因为它含有相邻自然数3和4。
把所有满足要求的子集记作S i,对于每一个S i计算出它的所有元素的乘积T i,求∑T i2。
【输入格式】仅一行,包括一个正整数n(n≤100)【输出格式】仅一行,即T i的平方和,可能会超出长整型范围。
【输入样例】4【输出格式】119题3:素数环(prime.???)【问题描述】给定一个n,求1..n组成的环,使得环上相邻的元素和为素数。
【输入格式】n(1<=n<=10)【输出格式】把1放在第一位置,按照字典顺序不重复的输出所有解(顺时针,逆时针算不同的两种),相邻两数之间严格用一个整数隔开,每一行的末尾不能有多余的空格。
【输入样例】8【输出样例】1 2 3 8 5 6 7 41 2 5 8 3 4 7 61 4 7 6 5 8 3 21 6 7 4 3 8 5 2题4:火力网(fire.???)【问题描述】在一个n*n的阵地中,有若干炮火不可摧毁的石墙,现在要在这个阵地中的空地上布置一些碉堡。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
注意:开始时商人,强盗所在的河的这边设为0状态,另一边设为1状态(也就是船开始时的一边设为0,当船驶到对岸是设为1状态,在这两个状态时,都必须符合条件)
#include<stdio.h>
#include <stdlib.h>
struct node /*建立一个类似栈的数据结构并且可以浏览每一个数据点*/
{
int x;
int y;
int state;
struct node *next;
};
typedef struct node state;
typedef state *link;
f1=f1+f2;/*前两个月加起来赋值给第三个月*/
f2=f1+f2;/*前两个月加起来赋值给第三个月*/
}
}
上题还可用一维数组处理
#include<stdio.h>
#define N 20
void main()
{
int a[N];
int i;
a[0]=a[1]=1;
for(i=2;i<N;i++)
{
if(Duhe(a,b-1,1)==1)
return 1;
}
else
{
Pop();
return 0;
}
}
if(n==1) /*判断0状态时,商匪状态是否符合要求*/
{
if(judge(a+1,b+1,2-a,2-b,0))
{
if(Duhe(a+1,b+1,0)==1)
return 1;
}
if(judge(a,b+2,3-a,1-b,0))
{
if(Duhe(a,b+2,0)==1)
return 1;
}
if(judge(a+2,b,1-a,3-b,0))
{
if(Duhe(a+2,b,0)==1)
return 1;
}
if(judge(a+1,b,2-a,3-b,0))
{
if(Duhe(a+1,b,0)==1)
return 1;
}
if(judge(a,b+1,3-a,2-b,0))
{
Push(a,b,n);
return 1;
}
else if(a==0)
{
Push(a,b,n);
return 1;
}
else if(a>=b)
{
Push(a,b,n);
return 1;
}
else return 0;
}
}
}
else return 0;
}
int Duhe(int a,int b,int n) /*递归法解决商人渡河问题,如果这一个状态符合*/
{
if(Duhe(a,b+1,0)==1)
return 1;
}
else
{
Pop();
return 0;
}
}
return 0;
}
main()
{
link pointer;
Push(3,3,0);
Duhe(3,3,0);
pointer=PPointer1;
while(pointer!=NULL)
{
printf( "%d,%d---%d\n ",pointer-> x,pointer-> y,pointer-> state);
newnode-> x=a;
newnode-> y=b;
newnode-> state=n;
newnode-> next=NULL;
if(PPointer1==NULL)
{
PPointer1=newnode;
PPointer2=newnode;
}
else
{
PPointer2-> next=newnode;
pointer=pointer-> next;
free(PPointer2);
PPointer2=pointer;
PPointer2-> next=NULL;
}
int history(int a,int b,int n) /*比较输入的数据和栈中是否有重复的*/
{
link pointer;
if(PPointer1==NULL)
{
a[i]=a[i-1]+a[i-2];
}
for(i=1;i<=N;i++)
{ printf("%12d",a[i-1]);
if(i%4==0)
printf("\n");
}
}
return 1;
else
{
pointer=PPointer1;
while(pointer!=NULL)
{
if(pointer-> x==a&&pointer-> y==b&&pointer-> state==n)
return 0;
pointer=pointer-> next;
}
return 1;
}
{ /*则判断下一个状态,直至问题解决*/
if(a==0&&b==0) return 1;
if(n==0) /*判断0状态时,商匪状态是否符合要求*/
{
if(judge(a-1,b-1,4-a,4-b,1))
{
if(Duhe(a-1,b-1,1)==1)
return 1;
}
if(judge(a,b-2,3-a,5-b,1))
答案:
1.#include <stdio.h>
int age(int n)
{ if(n==1) return(10);
else return age(n-1)+2;
}
void main()
{ int n;
n=5;
printf("The fifth age is %d.\n",age(n));
}
2.#include<conio.h>
si1=si;
}
printf("共有%d天,第一天的桃子数为%4d\n",N,si);
}
4.程序源代码:
main()
{long f1,f2;
int i;
f1=f2=1;
for(i=1;i<=20;i++)
{ printf("%12ld %12ld",f1,f2);
if(i%2==0) printf("\n");/*控制输出,每行四个*/
pointer=pointer-> next;
}
getch();
}
3.#include <stdio.h>
#include <stdlib.h>
#define N 30
void main()
{
int n, si,si1;
si1=1;
for(n=N-1;n>=1;n--)// Nhomakorabea数第二天开始
{
si=(si1+1)*2; //算出当天的桃子数
3.(用递推做)猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个,第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半多一个。到第30天早上想再吃时,见只剩下1个桃子了。求第一天共摘了多少。
4.(用递推做)已知一对兔子每一个月能生一对小兔子,而一对小兔子出生后第二个月就开始生小兔子,假如一年内没有发生死亡,则以对兔子一年能繁殖成多少对?
{
if(Duhe(a,b-2,1)==1)
return 1;
}
if(judge(a-2,b,5-a,3-b,1))
{
if(Duhe(a-2,b,1)==1)
return 1;
}
if(judge(a-1,b,4-a,3-b,1))
{
if(Duhe(a-1,b,1)==1)
return 1;
}
if(judge(a,b-1,3-a,4-b,1))
练习
1.(用递归做)5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?
程序分析:利用递归的方法,递归分为回推和递推两个阶段。要想知道第五个人岁数,需知道第四人的岁数,依次类推,推到第一人(10岁),再往回推。
link PPointer1=NULL;
link PPointer2=NULL;
int a1,b1;
int a2,b2;
/*栈中每个数据都分为0,1状态*/
void Push(int a,int b,int n)
{
link newnode;
newnode=(link)malloc(sizeof(state));
PPointer2=newnode;
}
}
void Pop() /*弹栈*/
{