递推-递归-分治-回溯
理解简单的递推与递归

理解简单的递推与递归递推和递归是计算机科学中常用的算法思想,用于解决问题的重要方法。
虽然递推和递归都是将问题分解为更小的子问题,但它们在问题求解过程中的实现方式和逻辑上的差异有所不同。
本文将从递推和递归的定义、应用场景、优缺点以及实例分析等方面展开讨论,帮助读者理解简单的递推与递归。
一、递推的定义和应用场景递推是一种从已知条件开始,通过一系列推导或迭代,得出问题的解的方法。
在递推中,我们通过已知的初始条件和一个或多个递推关系式来逐步推导出问题的解。
递推常用于描述数列、序列等问题,例如斐波那契数列、阶乘等。
通过寻找数列中相邻项之间的规律,并将规律表示为递推关系式,就可以使用递推的方式求解数列中的任意项。
以斐波那契数列为例,该数列的定义是:第一个和第二个数是1,从第三个数开始,每个数都是前两个数的和。
可以用递推关系式描述为:F(n) = F(n-1) + F(n-2),其中F(n)表示第n个斐波那契数。
通过这个递推关系式,我们可以从已知的初始条件F(1)=1和F(2)=1出发,逐步计算出数列中的其他项。
二、递归的定义和应用场景递归是一种将问题分解为更小子问题的方法,通过反复调用自身来解决问题。
递归的实现需要包含基本情况和递归调用两部分。
递归常用于描述树形结构、分治算法等问题。
例如,在遍历树的时候,我们可以通过递归地遍历左右子树来完成整棵树的遍历。
递归调用的过程中,会不断地将问题分解为更小的子问题,直到达到基本情况为止。
以计算阶乘为例,阶乘的定义是:n的阶乘等于n乘以(n-1)的阶乘,其中1的阶乘为1。
可以通过递归的方式计算阶乘。
三、递推与递归的优缺点比较1. 递推的优点:- 算法思路直观,易于理解和实现;- 执行效率高,因为递推是通过简单的迭代计算得出结果。
2. 递推的缺点:- 难以求解复杂的问题,有些问题可能无法找到明显的递推规律;- 需要明确的初始条件和递推关系式,如果这些条件和关系式不明确或者错误,可能导致计算结果错误。
回溯式结构

回溯式结构回溯式结构是一种通过重复调用自身来构建复杂结构的编程技术,用于解决某些有重复性的问题,它可以允许程序在遇到特定的边界条件(称为基本情况)时终止,可以将大型问题简化为多个小型子问题来求解,是一种分治法的典型代表。
回溯式结构可以非常有效地解决复杂问题,它更注重于分析、解决问题的过程,而不是解决方案,因此具有更强的灵活性和维度性。
它只需要一行代码就能实现,只要能够编写出准确、清晰的算法,就可以让计算机在处理复杂问题时实现最优效果。
回溯式结构与其他算法技术,如分治法、贪心法以及动态规划法相比,具有解决问题的有效途径。
回溯式结构的概念包括:递归、节点、回溯和基本情况。
递归一般用来描述问题可以被自身本身完全确定的解决方案,这种解决方案可以反复重复进行解决,以达到某种最终结果。
节点是递归算法的重要构成部分,每个节点都可以表示递归计算的一个步骤,也就是一个状态。
回溯是指从某个节点开始,经过尝试后,返回到之前的状态,重新尝试,这种过程叫做回溯。
基本情况则是递归的边界条件,即递归过程结束的条件。
举个例子,求一个整数n的阶乘,n!=n*(n-1)*(n-2)*...*1 。
这个问题可以采用回溯式结构来解决,首先,定义递归函数factorial,用来求解n的阶乘,有以下算法:(1)基本情况:t当n为1时,返回1;(2)节点:t对于n大于1的情况,递归调用factorial,即factorial(n)=n*factorial(n-1);(3)回溯:t每一次递归调用factorial都会返回某个固定的值,回溯过程从最后一个递归调用开始,逐步返回每个节点的值,当程序跳出最顶层的递归调用,最终得到n的阶乘。
回溯式结构的特点在于,它可以解决问题的过程,而不是一个完成的解决方案,这使得它可以灵活处理不同的问题。
例如,组合问题就可以通过回溯式结构来解决,如果有m种物品可以选择,每种物品可以选择n个,那么要求总共有多少种组合,就可以采用回溯式结构来求解。
第5讲 计算思维之常用算法设计

算法应用举例
【案例三】欧几里德算法
即辗转相除法,求两个数的最大公约数
两个整数的最大公约数(也称公因子)是能够同时整
除它们的正整数
辗转相除法求最大公约数
//辗转相除法求两整数m和n的最大公约数 Begin r ←m%n While(r!=0){ m n m ←n //迭代 n ←r //迭代 16 6 r←m%n } 6 4 Print 最大公约数n End 4 2
算法应用举例
【案例二】百钱买百鸡问题
百钱买百鸡:鸡翁一,值钱五 鸡母一,值钱三 鸡雏三,值钱一 问翁、母、雏各几何?
意思是:公鸡每只5元、母鸡每只3元、小鸡3只1元,用100元 钱买100只鸡,求公鸡、母鸡、小鸡的只数。
算法分析
设鸡翁、鸡母、鸡雏的个数分别为x、y、z,根据题意可得如下 方程组:
索范围 在此范围内对所有可能的情况逐一验证 若某个情况符合题目的条件,则为本题的一个答案;若全
部情况验证完后均不符合题目的条件,则问题无解。
算法应用举例
【案例一】警察破案 张三在家中遇害,侦查中发现A、B、C、D四人到过现场。 A说:“我没有杀人。” B说:“C是凶手。” C说:“杀人者是D” D说:“C在冤枉好人。”
r
4
2 0
计算思维之常用算法设计
1 2
3
穷举法 递推法
5 6
7
回溯法 分治法
递归法
迭代法
贪心法
动态规划
4 5
8
基本思想
回溯法实际上一个类似枚举的搜索尝试过程,主要是在搜索 尝试过程中寻找问题的解,当发现已不满足求解条件时,就 “回溯”返回,尝试别的路径。
回溯法即为: – “试探-失败返回-再试探”的问题求解方法,例 如:老鼠走迷宫。
计算机常用算法

练习: 假设有一堆小石子,二人轮流去取,谁拿走最后一颗石子便输。 先让甲规定石子总数N以及每次最多取多少颗数k(n>=2*k+1), 甲每次取a颗, (N,k,a均为随机数),乙怎样取赢的可能性最大? 设甲为计算机产生的随机数,乙为由你编的计算机程序。
贪心法是从问题的某一个初始解出发,向给定的目标推进.
数学函数式递归 例1、阶乘n!=1*2*3*…(n-1)*n
[算法分析]:要求n!,只需求出(n-1)!,因为n!=n*(n-1)!,要求出(n-1)!, 只需求出(n-2)!,因为(n-1)!=(n-1)*(n-2)!,所以可得到阶乘的递归定 义式:
n!=
{
n*(n-1)!,n>0; 1, n=0。
模拟法: 就是模拟某个过程,通过改变数学的各种参数,进而观察变更这 些参数所引起过程状态的变化.一般题目给定或者隐含某一概率.设 计者利用随机函数和取整函数设定某一范围的随机值,将符合概率 的随机值作为参数.然后根据这一模拟的数学模型展开算法. 模拟策略的关键: 是如何按照概率的要求确定随机值的范围.这个随机值设计得好, 模拟效果就好.
找零钱问题:一个小孩买了价值为33美分的糖,并将1 找零钱问题:一个小孩买了价值为33美分的糖,并将1美元 33美分的糖 的钱交给售货员。售货员希望用数目最少的硬币找给小孩。 的钱交给售货员。售货员希望用数目最少的硬币找给小孩。 假设提供了数目不限的面值为25美分、10美分 25美分 美分、 美分、 假设提供了数目不限的面值为25美分、10美分、5美分、及1 美分的硬币。 求解所用方法即为贪心算法) 美分的硬币。(求解所用方法即为贪心算法)
5 7 6
பைடு நூலகம்
本题目有9个格子,要求填数,如果不考虑问题给出的条件, 共有9!=362880种方案,在这些方案中符合条件的即为解。因 此可以用枚举法。
银行家算法例题详解算法设计题详解

银行家算法例题详解算法设计题详解算法设计的特征:有穷性,确定性,输入和输出,可行性运行算法的时间:硬件的速度。
书写程序的语言。
问题的规模,编译生成程序的代码质量算法复杂度: 时间复杂度和空间复杂度1.迭代法迭代法又称为辗转法,是用计算机解决问题的一种基本方法,为一种不断用变量的旧值递推新值的过程,与直接法相对应,一次性解决问题。
迭代法分为精确迭代和近似迭代,“二分法”和“牛顿迭代法”属于近似迭代法。
迭代法利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。
利用迭代算法解决问题,需要做好以下三个方面的工作:1. 确定迭代变量(在可以用迭代算法解决的问题中,至少存在一个直接或间接地不断由旧值递推出新值的变量,这个变量就是迭代变量。
)2. 建立迭代关系式(所谓迭代关系式,指如何从变量的前一个值推出其下一个值的公式(或关系)。
迭代关系式的建立是解决迭代问题的关键,通常可以顺推或倒推的方法来完成。
)3. 对迭代过程进行控制(在什么时候结束迭代过程?这是编写迭代程序必须考虑的问题。
不能让迭代过程无休止地重复执行下去。
迭代过程的控制通常可分为两种情况:一种是所需的迭代次数是个确定的值,可以计算出来;另一种是所需的迭代次数无法确定。
对于前一种情况,可以构建一个固定次数的循环来实现对迭代过程的控制;对于后一种情况,需要进一步分析出用来结束迭代过程的条件。
)2.穷举搜索法穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。
即本方法使用可以理解为暴力循环方法,穷举所有可能性,一般这种方法的时间效率太低,不易使用。
但是方法简单,易理解。
3.递推法递推是计算机数值计算中的一个重要算法,思路是通过数学推导,将复杂的运算化解为若干重复的简单运算,以充分发挥计算机长于重复处理的特点。
(一)八大算法思想

(⼀)⼋⼤算法思想⼋⼤算法⼋⼤算法:枚举、递推、递归、分治、贪⼼、试探法、动态迭代和模拟算法思想。
⼀、枚举算法思想(暴⼒算法) 将问题的所有可能答案⼀⼀列举,根据判断条件判断此答案是否合适,⼀般⽤循环实现。
经典运⽤:百钱买百鸡、填写运算符⼆、递推算法思想 1.顺推法:从已知条件出发,逐步推算出要解决问题的⽅法。
2.逆推法:从已知结果出发,⽤迭代表达式逐步推算出问题开始的条件,即顺推法的逆过程。
经典运⽤:斐波那契数列(顺推法)、银⾏存款(逆推法)三、递归算法思想 1.递归过程⼀般通过函数或⼦过程实现; 2.递归算法在函数或⼦过程的内部,直接或间接调⽤⾃⼰的算法 3.递归算法实际上是把问题转化为规模缩⼩了的同类问题的⼦问题,然后再递归调⽤函数或过程来表⽰问题的解 注意:必须有⼀个明确的递归结束条件;如果递归次数过多,容易造成栈溢出。
经典运⽤:汉诺塔问题、阶乘问题四、分治算法思想 将⼀个规模为N的问题分解为K个规模较⼩的⼦问题,这些⼦问题相互独⽴且与原问题性质相同。
只要求出⼦问题的解,就可得到原问题的解。
⼀般步骤: 1.分解,将要解决的问题划分成若⼲个规模较⼩的同类问题 2.求解,当⼦问题划分得⾜够⼩时,⽤较简单的⽅法解决 3.合并,按原问题的要求,将⼦问题的解逐层合并构成原问题的解 经典运⽤:⼤数相乘问题、⽐赛⽇程安排五、贪⼼算法思想 从问题的某⼀个初始解出发,逐步逼近给定的⽬标,以便尽快求出更好的解。
局限: 不能保证最后的解是最优的; 不能求最⼤最⼩解问题; 只能求满⾜某些约束条件的可⾏解范围。
基本过程: 1.从问题的某⼀初始解出发 2.while能向给定总⽬标前进⼀步 3.求出可⾏解的⼀个解元素 4.由所有解元素组合成问题的⼀个可⾏解 经典运⽤:装箱问题、找零⽅案六、试探算法(回溯法) 在试探算法中,放弃当前候选解,并继续寻找下⼀个候选解的过程称为回溯。
扩⼤当前候选解的规模,以继续试探的过程称为向前试探。
常用算法设计方法C语言

常用算法设计方法C语言常用算法设计方法 (1)一、迭代法 (1)二、穷举搜索法 (2)三、递推法 (6)四、递归 (7)五、回溯法 (15)六、贪婪法 (28)七、分治法 (33)八、动态规划法 (39)常用算法设计方法要使计算机能完成人们预定的工作,首先必须为如何完成预定的工作设计一个算法,然后再根据算法编写程序。
计算机程序要对问题的每个对象和处理规则给出正确详尽的描述,其中程序的数据结构和变量用来描述问题的对象,程序结构、函数和语句用来描述问题的算法。
算法数据结构是程序的两个重要方面。
算法是问题求解过程的精确描述,一个算法由有限条可完全机械地执行的、有确定结果的指令组成。
指令正确地描述了要完成的任务和它们被执行的顺序。
计算机按算法指令所描述的顺序执行算法的指令能在有限的步骤内终止,或终止于给出问题的解,或终止于指出问题对此输入数据无解。
通常求解一个问题可能会有多种算法可供选择,选择的主要标准是算法的正确性和可靠性,简单性和易理解性。
其次是算法所需要的存储空间少和执行更快等。
算法设计是一件非常困难的工作,经常采用的算法设计技术主要有迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法等等。
另外,为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。
一、迭代法迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。
设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行:选一个方程的近似根,赋给变量x0;将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0;当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。
若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。
上述算法用C程序的形式表示为:【算法】迭代法求方程的根{ x0=初始近似根;d o {x1=x0;x0=g(x1);/*按特定的方程计算新的近似根*/} while ( fabs(x0-x1)>Epsilon);p rintf(“方程的近似根是%f\n”,x0);}迭代算法也常用于求方程组的根,令X=(x0,x1,…,xn-1)设方程组为:xi=gi(X) (I=0,1,…,n-1)则求方程组根的迭代算法可描述如下:【算法】迭代法求方程组的根{ for (i=0;i<n;i++)x[i]=初始近似根;do {for (i=0;i<n;i++)y[i]=x[i];for (i=0;i<n;i++)x[i]=gi(X);for (delta=0.0,i=0;i<n;i++)if (fabs(y[i]-x[i])>delta)delta=fabs(y[i]-x[i]);} while (delta>Epsilon);for (i=0;i<n;i++)printf(“变量x[%d]的近似根是%f”,I,x[i]);printf(“\n”);}具体使用迭代法求根时应注意以下两种可能发生的情况:如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给予限制;方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,也会导致迭代失败。
算法设计技巧与分析

算法设计技巧与分析算法设计技巧是计算机科学领域中非常重要的一部分。
一个好的算法能够提高程序的效率,减少资源的消耗。
算法设计的技巧有很多种,比如递归、分治、贪心、动态规划等等。
以下将对一些常用的算法设计技巧进行分析和讨论。
递归是一种非常常见的算法设计技巧。
递归是指一个函数在执行的过程中会调用自身。
递归通常需要一个基本的情况和一个递推的情况。
递归的好处是能够简化问题的求解过程,但是递归也有一些缺点,比如递归的深度过大会导致栈溢出的问题。
在设计递归算法时,需要注意避免这种情况的发生。
分治是一种将问题分解成多个子问题并将子问题的解合并起来得到最终解的算法设计技巧。
分治算法通常可以通过递归来实现。
在设计分治算法时,需要注意子问题之间的关系,以及如何将子问题的解合并起来。
贪心是指每一步都选择当前最优解的算法设计技巧。
贪心算法通常需要证明每一步的最优解一定能够导致最终的最优解。
贪心算法的好处是简单、高效,但是贪心算法不能解决所有的问题,有些问题需要使用动态规划等其他算法进行求解。
动态规划是一种将问题分解成多个子问题并选择最优的子问题解组合得到最终解的算法设计技巧。
动态规划通常需要一个表格来存储中间的结果,以便后续的计算。
在设计动态规划算法时,需要注意问题的重叠子问题特性,以及如何利用已经计算过的结果来加速计算。
在进行算法设计时,还需要考虑时间复杂度和空间复杂度。
时间复杂度是用来衡量算法执行时间的参数,通常用“大O记法”来表示。
空间复杂度是用来衡量算法消耗的空间的参数,也用“大O记法”来表示。
在算法设计中,通常要追求时间复杂度和空间复杂度尽量低。
除了以上几种常见的算法设计技巧外,还有很多其他的算法设计技巧,比如回溯、剪枝等等。
在实际的算法设计中,不同的问题可能需要采用不同的算法设计技巧。
因此,对算法设计技巧的熟练掌握和运用是非常重要的。
综上所述,算法设计技巧与分析是计算机科学中的重要内容。
通过合理选择和运用不同的算法设计技巧,能够提高程序的效率,从而更好地解决问题。
程序设计基础(C语言)第6章 程序设计的问题求解基础

6.2枚举——从找回你的密码谈起
#include <stdio.h> int main(void) {
影响算法的时间复杂度 循环结构实现
确定 判定条件
符合答案的条件 分支结构实现
for (穷举范围) {
…… if (符合答案的条件)
…… }
6.2枚举——从找回你的密码谈起
• 【例6.1】百鸡问题是我国古代数学名著《张丘建算经》中的一个著名数学问题,它给出了 由三个未知量的两个方程组成的不定方程组的解。《张丘建算经》为北魏张丘建所著,所 载问题大部分为当时社会生活中的实际问题,如有关测量、纺织、交换、纳税、冶炼、土 木工程等,涉及面广泛,其问题和解法均超出《九章算术》。
第6章 程序设计的问题求解基础
6.1问题求解策略
算法设计的基本思路就是寻找解决问题的规律。 指在数学思想支持下的解题思路、方式和方法。 常用的问题求解策略
枚举、递推、迭代、分治、递归
6.2枚举——从找回你的密码谈起
穷举法(Exhaustion),也称枚举法(Enumeration )
列举所有可能,逐一试探
输入:无;输出:士兵至少x人
确定穷举对象:士兵数x 确定搜索范围:x从1变化…… 确定判定条件:x被5、6、7、11整除余数为1、5、4、10 x%5==1 && x%6==5 && x%7==4 && x%11==10
6.2枚举——从找回你的密码谈起
算法之2章递归与分治

算法分析(第二章):递归与分治法一、递归的概念知识再现:等比数列求和公式:1、定义:直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
2、与分治法的关系:由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归经常同时应用在算法设计之中,并由此产生许多高效算法。
3、递推方程:(1)定义:设序列01,....na a a简记为{na},把n a与某些个()ia i n<联系起来的等式叫做关于该序列的递推方程。
(2)求解:给定关于序列{n a}的递推方程和若干初值,计算n a。
4、应用:阶乘函数、Fibonacci数列、Hanoi塔问题、插入排序5、优缺点:优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
二、递归算法改进:1、迭代法:(1)不断用递推方程的右部替代左部(2)每一次替换,随着n的降低在和式中多出一项(3)直到出现初值以后停止迭代(4)将初值代入并对和式求和(5)可用数学归纳法验证解的正确性2、举例:-----------Hanoi塔算法----------- ---------------插入排序算法----------- ()2(1)1(1)1T n T nT=−+=()(1)1W n W n nW=−+−(1)=021n-23()2(1)12[2(2)1]12(2)21...2++2 (121)n n n T n T n T n T n T −−=−+=−++=−++==++=−(1)2 ()(1)1((n-2)+11)1(2)(2)(1)...(1)12...(2)(1)(1)/2W n W n n W n n W n n n W n n n n =−+−=−−+−=−+−+−==++++−+−=−3、换元迭代:(1)将对n 的递推式换成对其他变元k 的递推式 (2)对k 进行迭代(3)将解(关于k 的函数)转换成关于n 的函数4、举例:---------------二分归并排序---------------()2(/2)1W n W n n W =+−(1)=0(1)换元:假设2kn =,递推方程如下()2(/2)1W n W n n W =+−(1)=0 → 1(2)2(2)21k k k W W W−=+−(0)=0(2)迭代求解:12122222321332133212()2(2)212(2(2)21)212(2)22212(2)2*2212(2(2)21)2212(2)222212(2)3*2221...2(0)*2(22...21)22k k k k k k k k k k k k k k k k k k k k k k k k W n W W W W W W W W k k −−−−−−−+−+−−−=+−=+−+−=+−+−=+−−=+−+−−=+−+−−=+−−−==+−++++=−1log 1n n n +=−+(3)解的正确性—归纳验证: 证明递推方程的解是()(1)/2W n n n =−()(1)1W n W n n W =−+−(1)=0,(n 1)=n +n=n(n-1)/2+n =n[(n-1)/2+1]=n(n+1)/2n W W +方法:数学归纳法证 n=1,W(1)=1*(1-1)/2=0假设对于解满足方程,则()---------------快速排序--------------------->>>平均工作量:假设首元素排好序在每个位置是等概率的112()()()(1)0n i T n T i O n n T −==+=∑ >>>对于高阶方程应该先化简,然后迭代(1)差消化简:利用两个方程相减,将右边的项尽可能消去,以达到降阶的目的。
计算机算法设计五大常用算法的分析及实例

计算机算法设计五⼤常⽤算法的分析及实例摘要算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。
也就是说,能够对⼀定规范的输⼊,在有限时间内获得所要求的输出。
如果⼀个算法有缺陷,或不适合于某个问题,执⾏这个算法将不会解决这个问题。
不同的算法可能⽤不同的时间、空间或效率来完成同样的任务。
其中最常见的五中基本算法是递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法。
本⽂通过这种算法的分析以及实例的讲解,让读者对算法有更深刻的认识,同时对这五种算法有更清楚认识关键词:算法,递归与分治法、动态规划、贪⼼算法、回溯法、分⽀限界法AbstractAlgorithm is the description to the problem solving scheme ,a set of clear instructions to solve the problem and represents the describe the strategy to solve the problem using the method of system mechanism . That is to say, given some confirm import,the Algorithm will find result In a limited time。
If an algorithm is defective or is not suitable for a certain job, it is invalid to execute it. Different algorithms have different need of time or space, and it's efficiency are different.There are most common algorithms: the recursive and divide and conquer、dynamic programming method、greedy algorithm、backtracking、branch and bound method.According to analyze the five algorithms and explain examples, make readers know more about algorithm , and understand the five algorithms more deeply.Keywords: Algorithm, the recursive and divide and conquer, dynamic programming method, greedy algorithm、backtracking, branch and bound method⽬录1. 前⾔ (4)1.1 论⽂背景 (4)2. 算法详解 (5)2.1 算法与程序 (5)2.2 表达算法的抽象机制 (5)2.3 算法复杂性分析 (5)3.五中常⽤算法的详解及实例 (6)3.1 递归与分治策略 (6)3.1.1 递归与分治策略基本思想 (6)3.1.2 实例——棋盘覆盖 (7)3.2 动态规划 (8)3.2.1 动态规划基本思想 (8)3.2.2 动态规划算法的基本步骤 (9)3.2.3 实例——矩阵连乘 (9)3.3 贪⼼算法 (11)3.3.1 贪⼼算法基本思想 (11)3.3.2 贪⼼算法和动态规划的区别 (12)3.3.3 ⽤贪⼼算法解背包问题的基本步骤: (12)3.4 回溯发 (13)3.4.1 回溯法基本思想 (13)3.3.2 回溯发解题基本步骤 (13)3.3.3 实例——0-1背包问题 (14)3.5 分⽀限界法 (15)3.5.1 分⽀限界法思想 (15)3.5.2 实例——装载问题 (16)总结 (18)参考⽂献 (18)1. 前⾔1.1 论⽂背景算法(Algorithm)是指解题⽅案的准确⽽完整的描述,是⼀系列解决问题的清晰指令,算法代表着⽤系统的⽅法描述解决问题的策略机制。
易语言算法集合概要

常用算法设计概括地说,“算法”是指解题方案的准确而完整的描述。
对于一个问题,如果可以通过一个计算机程序,在有限的存储空间内进行有限长的时间而得到正确的结果,则称该问题是算法可解的。
但算法不等于程序,也不等于计算方法。
程序可以作为算法的一种描述,但程序通常还需考虑很多与方法和分析无关的细节问题,这是因为在编写程序时要受到计算机系统运行环境的限制。
通常,程序设计的质量不可能优于算法的设计。
通常求解一个问题可能会有多种算法可供选择,选择的主要标准是算法的正确性和可靠性,简单性和易理解性。
其次是算法所需要的存储空间少和执行更快等。
算法设计是一件非常困难的工作,经常采用的算法设计技术主要有列举法、递推法、贪婪法、回溯法、分治法、动态规划法等等。
另外,为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。
1.列举法(穷举)列举法的基本思想是根据提出的问题,列举所有可能情况,并用问题中提出的条件检验哪些是需要的,哪些是不需要的。
因此,列举法常用于解决“是否存在”或“有多少种可能”等类型的问题。
例如,求解不定方程的问题可以采用列举法。
列举法的特点是算法比较简单,但当列举的可能情况较多时,执行列举算法的工作量将会很大。
因此,在用列举法设计算法时,应该重点注意使方案优化,尽量减少运算工作量。
通常,只要对实际问题作详细的分析,将与问题有关的知识条理化、完备化、系统化,从中找出规律,或对所有可能的情况进行分类,引出一些有用的信息,列举量是可以减少的。
先介绍“列举法”在易语言中实现的方法。
列举法,顾名思义是列举出所有可能的情况,并用问题的条件来一一检验,并从中找出符合要求的解。
特点比较简单,但是在写列举算法时尽量过滤掉一些不必要的情况,优化算法。
下面举一个例子,在易语言中编写代码实现,来说明列举法的基本思想,以及如何减少列举量。
大家都知道百鸡的问题吧!母鸡每只3元,公鸡每只2元,小鸡每只0.5元,计算一下如何100块钱买100只鸡。
离散数学中的递归与递推知识点区分

离散数学中的递归与递推知识点区分递归和递推作为离散数学中的重要概念,常常被混淆使用。
虽然两者都涉及到数列或函数的定义和计算,但它们在思想和方法上存在一些明显区别。
本文将从定义、特点和应用等方面对递归和递推进行深入探讨,以期帮助读者准确理解并运用两者。
一、递归的基本概念和特点递归是指在数学中,一个定义中出现对所定义对象本身的描述。
简而言之,就是一个问题的解能够通过不断地调用相同问题的解来进行求解。
举一个简单的例子,阶乘的递归定义如下:n! = n * (n-1)!从上述定义可以看出,阶乘的计算通过不断地调用相同问题的解来进行求解。
递归具有以下几个基本特点:1. 终止条件:递归定义中必须包含一个或多个终止条件,以避免无限递归的发生。
在阶乘的例子中,当n等于0或1时,阶乘的值已经确定,不需要再进行递归调用。
2. 自相似性:递归定义中的每一步都与问题本身具有相同的性质,即通过不断缩小问题的规模来求解。
在上述阶乘的例子中,每一步的计算都与整个阶乘的计算过程相同,只是问题规模减少了。
3. 递归调用:在递归中,问题的解不断地通过调用相同问题的解来获得。
在阶乘的例子中,计算n的阶乘需要先计算(n-1)的阶乘。
二、递推的基本概念和特点递推是指通过已知的初始条件和规则,根据已知的项计算后续的项。
递推是用迭代的方式进行计算,其中每一步的计算仅依赖于之前的计算结果。
举一个简单的例子,斐波那契数列的递推定义如下:F(n) = F(n-1) + F(n-2),其中F(0) = 0, F(1) = 1递推具有以下几个基本特点:1. 初始条件:递推定义中必须包含一个或多个初始条件,以确定计算的起点。
在斐波那契数列的例子中,初始条件是F(0)和F(1)的取值。
2. 依赖关系:递推定义中每一项的计算都依赖于之前的计算结果。
在斐波那契数列的例子中,要计算第n项,需要先计算第n-1项和第n-2项。
3. 迭代计算:递推通过迭代计算的方式来求解问题,每一步都可以通过已知的计算结果得到下一步的计算结果。
软考教材分享:程序员考试考点分析与真题详解(第4版)

程序员考试考点分析与真题详解(第4版)第 1 章数据结构与算法数据结构是指数据对象及其彼此关系和构造方式,一个数据结构S可以用一个二元组表示为S=(D,R)。
其中,D是数据结构中的数据的非空有限集合,R是概念在D上的关系的非空有限集合。
在数据结构中,结点与结点间的彼此关系称为数据的逻辑结构,数据在计算机中的存储形式称为数据的存储结构。
数据结构按逻辑结构不同分为线性结构和非线性结构两大类,其中非线性结构又可分为树形结构和图结构,而树形结构又可分为树结构和二叉树结构。
依照考试大纲的要求,在数据结构与算法方面,要求考生掌握以下知识点。
1.常常利用数据结构数组(一维数组、二维数组、静态数组、动态数组)、线性表、链表(单向链表、双向链表、环形链表)、队列、栈、树(二叉树、查找树)和图(邻接矩阵、邻接表)等的概念、存储和操作。
2.常常利用算法(1)排序算法、查找算法、数值计算算法、字符串处置算法、递归算法、最小生成树、拓扑排序和单源点最短路径求解算法、图的相关算法。
(2)算法与数据结构的关系、算法效率、算法设计、算法描述(流程图、伪代码、决策表)、算法的复杂性。
1.1 算法设计概述算法是在有限步骤内求解某一问题所利用的一组概念明确的规则。
通俗地说,就是计算机解题的进程。
在这个进程中,无论是形成解题思路仍是编写程序,都是在实施某种算法。
前者是推理实现的算法,后者是操作实现的算法。
一个算法应该具有以下5个重要的特征。
(1)有穷性:一个算法(对任何合法的输入值)必需老是在执行有穷步以后结束,且每一步都可在有穷时间内完成。
(2)肯定性:算法中每一条指令必需有确切的含义,读者理解时不会产生二义性。
在任何条件下,算法只有唯一的一条执行路径,即对于相同的输入只能得出相同的输出。
(3)输入:一个算法有零个或多个输入,以肯定运算对象的初始情况。
所谓零个输入是指算法本身定出了初始条件。
这些输入取自于某个特定对象的集合。
(4)输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果。
算法的分类

算法的分类算法是计算机科学中的重要概念,是指在一系列规则或指示下,通过一定的计算方式,解决特定的问题或完成特定的任务。
算法的分类可以根据不同的特征进行划分,下面将就这个话题进行详细探讨。
一、按照算法的基本操作方式分类1.递推算法递推算法是指根据已知的数据推算出未知数据的方法,其计算比较简单,容易理解。
常见的递推算法有斐波那契数列、汉诺塔问题等。
2.分治算法分治算法是把大问题不断分解成小问题,直到小问题可以简单的解决,然后逐步合并解决小问题的解法,得到原大问题的计算结果。
常见的分治算法有快速排序、归并排序等。
3.回归算法回归算法是通过分析已有数据的相关性,预测未来结果的算法。
主要用于统计分析和经济学领域。
枚举算法是指把所有的可能性都列出来,一一列举分析,得出结果的算法。
常见的枚举算法有全排列问题、最短路径问题等。
5.贪心算法贪心算法是通过对每一个问题选择当前最好的解决方法,在所有结果中找到最优解的算法。
常见的贪心算法有背包问题、最小生成树问题等。
6.动态规划算法动态规划算法是通过把大问题分解成一系列子问题,依次求解每个子问题的最优解,从而得出整个问题的最优解的算法。
常见的动态规划算法有最长公共子序列问题、最长上升子序列问题等。
二、按照算法的应用场景分类1.排序算法排序算法是指将一定序列的元素按照指定的大小关系进行排序的算法。
常见的排序算法有冒泡排序、选择排序、快速排序、堆排序等。
图论算法是指对图的相关概念及其表示方法进行研究的算法。
常见的图论算法有最短路径算法、最小生成树算法、最大流算法等。
3.字符串算法字符串算法是指对字符串相关概念及其处理方式进行研究的算法。
常见的字符串算法有字符串匹配算法、子串查找算法等。
4.数值计算算法数值计算算法是指对数值计算问题进行研究的算法。
常见的数值计算算法有数值积分算法、线性方程组求解算法、常微分方程数值解法等。
5.人工智能算法人工智能算法是指通过对人类智能的模拟,实现特定任务的算法。
信息奥赛中的数学方法

03
信息奥赛不仅考察参赛者的编 程能力,还注重考察其算法设 计、数据结构、数学逻辑等多 方面的综合素质。
数学方法在信息奥赛中的应用
数学方法是信息奥赛中的重要工具,广泛应用于问题建模、算法设计、复 杂度分析等方面。
常用的数学方法包括组合数学、数论、图论、概率论与统计等,这些方法 对于解决信息奥赛中的问题具有关键作用。
整数分解算法
将一个合数分解成若干个质数的乘积,常用算法有 试除法和Pollard's rho算法。
模线性方程求解算法
求解形如ax ≡ b (mod m)的模线性方程,常 用算法有扩展欧几里得算法和中国剩余定理。
06 数学方法在信息奥赛中的 综合应用
问题建模与转化
抽象问题为数学模型
将实际问题中的关键信息提取出来,用数学语言进行描述,建立 相应的数学模型。
信息奥赛中的数学方法
contents
目录
• 绪论 • 基础知识 • 初级算法 • 中级算法 • 高级算法 • 数学方法在信息奥赛中的综合应用
01 绪论
信息奥赛简介
01
信息奥赛,即信息学奥林匹克 竞赛,是面向中学生的一项富 有挑战性和创造性的计算机科 学竞赛活动。
02
旨在通过竞赛活动培养和选拔 优秀计算机人才,推动计算机 科学技术在青少年中的普及和 深入。
与他人交流解题过程中的心得与 体会,分享经验和技巧,共同提 高解题水平。
THANKS FOR WATCHING
感谢您的观看
掌握数学方法不仅可以帮助参赛者更好地理解问题本质,还可以提高其解 题效率和准确性。
学习目的与意义
学习数学方法对于参加信息 奥赛具有重要意义,可以提 高参赛者的算法设计能力和
c++复习总结

C++语言程序设计复习总结1. 计算机软件——程序 + 文档 + 所需数据2. 程序可用公式概括地表述为:程序 = 算法 + 数据结构(程序设计方法学)3. 算法、语言和程序一个算法必须具备的基本特征:有穷性、确定性、0~n个数据输入及数据输出、可行性常用的基础算法:穷举法、迭代法、递归法、递推法、分治法、回溯法4. 软件开发工程化和软件生存期5. C/C++语言的优点和缺点6. C程序设计语言十分便于采用自顶向下、逐步细化的结构化程序设计技术7. 数据描述与基本操作(常量、变量、数据类型和运算符)8. 任何一个算法可用三种基本结构表示(顺序、 if选择、 while循环)9. if和else不是必定成对出现。
10.完全可用 if 取代 switch 编写程序(反之亦然)11.当利用for语句来实现无限循环时,不能将for后圆括号中的所有内容都省略不写。
for(e1;e2;e3)==>for(;;)12.复合语句是一组由花括号括起来的语句组,它等价为一条语句。
13.在循环算法中,穷举与迭代是两类具有代表性的基本算法。
14.用计数法进行循环控制时, 要先确定循环次数,再逐次测试,完成测试次数循环结束。
用标志法进行循环控制时,达到某一目标时,循环结束。
15. break、continue、goto和return非结构化语句可以改变程序的执行顺序。
16.用算法最小集及其嵌套引用实现的算法,称之为结构化算法。
17.C++中的变量名(或标识符)可以区分大小写。
18.任何C++程序都是由一个主函数和0至n个其它函数组成,主函数名一律用main,其它函数名自定。
若有类定义,可用.h头文件保存,类中的实现部分用.cpp文件保存,分别编译各个.cpp文件后,再链接、运行。
19.应用指针时,先定义、赋值后使用。
20.若已有说明语句: int a[10],*pa=a; 则a[i]、*(pa+i)、*(a+i)或pa[i]都是完全同样功能的表达式。
递归和回溯

递归和回溯递归和回溯是计算机科学中重要的概念,它们被广泛地应用在算法和程序设计中。
递归(Recursion)是指一种程序设计技术,它将问题的解决方法分解为更小的子问题,依次解决子问题,最后将各个子问题的解合并起来得到问题的解。
而回溯(Backtracking)则是指一种试探性的搜索算法。
回溯算法通过递归依次试探问题的每一种可能解决办法,对于无解或者不符合要求的情况进行回溯,寻找新的解决方案。
本文将从定义、应用、优化三方面详细讲解递归和回溯算法。
一、递归的定义及应用1.1 递归的概念递归是一种程序设计技巧,它将一个问题分解为更小的子问题,问题的解决方法与子问题的解决方法相同,通过递归调用子问题的解决方法,最终得到问题的解决方法。
递归有两个必要条件:一是递归终止条件(递归出口);二是递归调用(自调用)。
综上所述,递归程序必须具备的特点是具有递归出口和自调用两个基本属性。
1.2 递归的应用递归在程序设计中的应用非常广泛,常见的应用包括:树结构遍历、排序、搜索、字符串处理、图的深度优先搜索等等。
递归应用最为广泛的领域是算法和操作系统。
在算法领域中,递归是解决分治、动态规划等问题的主要思想,如快速排序、归并排序和斐波那契数列等都是基于递归设计的。
在操作系统中,递归的应用也比较广泛,比如UNIX系统中使用递归算法实现打印目录下所有文件的函数,Windows系统中使用递归算法查询注册表等。
1.3 实例分析:斐波那契数列斐波那契数列是指:1、1、2、3、5、8、13、21、34、……。
其中第1项和第2项为1,从第3项开始,每一项为前两项的和。
斐波那契数列可以用递归方式写出如下代码:```c++ int fib(int n) { if (n <= 2){ return 1; } return fib(n - 1) + fib(n - 2); } ```该递归函数表示了斐波那契数列的定义,在递归函数中,首先判断n是否小于等于2,如果是,直接返回1;如果不是,继续递归调用fib(n-1)和fib(n-2),最后将两个递归函数的返回结果相加作为函数的返回结果。
算法相关的名词解释

算法相关的名词解释算法是计算机科学的核心和基石,无论是数据处理,图像处理,自然语言处理,机器学习,还是人工智能领域的各种应用,都离不开算法。
为了更好地理解相关的名词,我们将对一些常见的算法名词进行解释。
一、贪心算法贪心算法是一种通过做出每一步最优选择,从而达到整体最优的算法。
贪心算法无法保证结果是最优解,但由于其高效性,常用于近似解问题。
贪心算法每次选择局部最优解,并且不回溯。
虽然贪心算法简单易懂,但在应用时需要斟酌每一步最优选择是否真的能够达到整体最优。
二、分治算法分治算法是一种将问题分解为更小规模的子问题,并递归地解决各个子问题,最终将子问题的解合并得到整体解的算法。
分治算法常用于解决规模较大的问题,如排序、查找、图形问题等。
典型的分治算法例子包括归并排序和快速排序。
三、动态规划动态规划是一种通过将问题分解为相互重叠的子问题,用数组保存子问题的解,最终得到整体解的算法。
动态规划在求解最短路径、背包问题等方面具有广泛应用。
动态规划算法通常包括定义状态、状态转移方程以及初始条件等步骤。
四、回溯算法回溯算法是一种通过穷举所有可能解并逐步筛选得到最优解的算法。
回溯算法常用于解决组合问题、排列问题、八皇后问题等。
回溯算法通常采用递归的方式,通过深度优先搜索遍历问题的解空间。
五、遗传算法遗传算法是一种受到生物进化理论启发而发展起来的优化算法。
遗传算法模拟自然选择、交叉、变异等过程,通过种群的进化搜索问题的最优解。
遗传算法常用于求解复杂问题,如旅行商问题和机器学习中的参数优化。
六、神经网络神经网络是一种模拟人脑神经元连接和传输过程的数学模型,其由输入层、隐藏层和输出层组成。
神经网络通过学习样本数据,调整连接权重,从而实现对问题的预测和分类。
神经网络在图像识别、语音识别等领域具有广泛应用。
七、支持向量机支持向量机是一种用于分类和回归分析的监督学习模型。
支持向量机通过寻找一个最优超平面将不同类别的样本进行划分。
1.2-设计方法

Tromino Puzzle
6. 回溯法
例:求解皇后问题
1 2 3 4 5 6 7 8
由n2 个方块排成n行n列的
1 Q 正方形称为“n元棋盘”。 2 Q 如果两个皇后位于棋盘上 3 Q 的同一行或同一列或同 4 Q 一对角线上,则称它们 5 Q 6 Q 为互相攻击。 现要求找使n元棋盘上的n 7 Q Q 个皇后互不攻击的所有 8
c11 x1 x4 x5 x7 c x x 12 3 5 c21 x2 x4 c22 x1 x3 x2 x 6
采用减半递推技术 + Strassen 矩阵乘法 计算两个n阶矩阵相乘 A和B是两个n×n矩阵 n=2k
将 C = AB 重写为
两个2阶矩阵相乘需作乘法次数 8 = 23次
矩阵乘法 C = AB
设A和B是两个n×n的矩阵
cij aik bkj
k 1
n
两个n阶矩阵相乘需作乘法次数 n3次
采用减半递推技术 (分治算法)
A和B是两个n×n矩阵 n=2k
将A,B,C中每个矩阵都分块成4个大小相等的子矩阵 每个子矩阵是n/2阶方阵
OUTPUT n } RETURN
PROCEDURE WRT1(1) IF (n≠0) THEN { WRT1(1-1)
OUTPUT n } RETURN
PROCEDURE WRT1(0) IF (n≠0) THEN { WRT1(0-1) OUTPUT n } RETURN
3
2
1
补充例:Hanoi塔
2. 归纳法
通过列举少量的特殊情况,经过分 析,最后找出一般的关系。
3. 递推
初始条件 递推关系式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
递推算法在程序编辑过程中,我们可能会遇到这样一类问题,出题者告诉你数列的前几个数,或通过计算机获取了数列的前几个数,要求编程者求出第N项数或所有的数列元素(如果可以枚举的话),或求前N项元素之和。
这种从已知数据入手,寻找规则,推导出后面的数的算法,称这递推算法。
典型的递推算法的例子有整数的阶乘,1,2,6,24,120…,a[n]=a[n-1]*n(a[1]=1);前面学过的2n,a[n]=a[n-1]*2(a[1]=1),菲波拉契数列:1,2,3,5,8,13…,a[n]=a[n-1]+a[n-2](a[1]=1,a[2]=2)等等。
在处理递推问题时,我们有时遇到的递推关系是十分明显的,简单地写出递推关系式,就可以逐项递推,即由第i项推出第i+1项,我们称其为显示递推关系。
但有的递推关系,要经过仔细观察,甚至要借助一些技巧,才能看出它们之间的关系,我们称其为隐式的递推关系。
下面我们来分析一些例题,掌握一些简单的递推关系。
例如阶梯问题:题目的意思是:有N级阶梯,人可以一步走上一级,也可以一步走两级,求人从阶梯底走到顶端可以有多少种不同的走法。
这是一个隐式的递推关系,如果编程者不能找出这个递推关系,可能就无法做出这题来。
我们来分析一下:走上第一级的方法只有一种,走上第二级的方法却有两种(两次走一级或一次走两级),走上第三级的走法,应该是走上第一级的方法和走上第二级的走法之和(因从第一级和第二级,都可以经一步走至第三级),推广到走上第i级,是走上第i-1级的走法与走上第i-2级的走法之和。
很明显,这是一个菲波拉契数列。
到这里,读者应能很熟练地写出这个程序。
在以后的程序习题中,我们可能还会遇到菲波拉契数列变形以后的结果:如f(i)=f(i-1)+2f(i-2),或f(i)=f(i-1)+f(i-2)+f(i-3)等。
我们再来分析一下尼科梅彻斯定理。
定理内容是:任何一个整数的立方都可以写成一串连续的奇数和,如:43=13+15+17+19=64。
从键盘输入一个整数n,要求写出其相应的连续奇数。
我们不妨从简单入手,枚举几个较小的数据:13=123=3+533=7+9+1143=13+15+17+1953=21+23+25+27+29根据上面的例子,读者不难看出:(1)输入为n时,输出应有n项。
(2)输入分别为1,2,3…时,则输出恰好为连续奇数,1,3,5,7,9,11…即下一行的首项比上一行的末项大2。
经上面的分析,原本看不出递推关系的问题,呈现出递推关系。
在趣的是,这个例子的递推过程,可以有多种算法。
算法一:将所有奇数逐项例举出来,然后将其分段,即:1; 3 5; 7 9 11; 13 15 17 19; 21…1 2 3 4 5…算法二、设输入为n时的输出第一项为a[n],则a[n]=a[n-1]-n+1;于是我们推出首项后,则输出为a[n]+a[n]+2+…+a[n]+2(n-1)算法三、进一步总结,不难得出,若输入为n时,首项a[n]=n2-n+1,其余同算法二。
下面我们来分析两个与动物有关的趣题。
这个题目中,读者不难理解,如果狼每次都能走入一个以前没有到过的洞中,则无论兔子怎么躲藏,都不能幸免遇狼。
若狼跳越若干次后,不仅走到了以前到过的洞中,而且要跳越的洞数又与以前的某次相同,则狼就会循环往复地在同一些洞中跳来跳去,成为小丑而无法跳入以前没有到过的洞中。
这些洞恰恰就是兔子的安全洞穴。
基于以上的分析,兔子有安全洞穴的条件有三,一是狼经过若干次跳跃后,回到原来到过的洞中;二是同一洞历史上的某一次跳越的洞数与即将要跳的这一次跨越的洞数也相同;三是到此时为止,狼应有从未到过的洞穴。
基本的算法是:从1号洞开始,按11->32->63->104->45->106->……方式,由前一个状态推导出下一个状态,同时将每一个新状态与前面存贮下来的状态作比较,以便找到两个可以作结论的状态。
即要么狼已走遍了所有兔子洞,要么狼卷入死循环,而有些洞无法进入。
那么,现在我们怎样来存贮这些状态呢?最简单的办法是计数。
我们对每个洞建立一个数组,用来记载这个洞狼是否到过,在这个洞中跳越洞数,以及另一个趣题是猴子吃桃问题:山中住有五只猴。
一天,老大看见一堆桃子,想把桃子据为已有,却担心让老二老三知道了说自己太贪心。
于是将桃分成相等的两份,却发现剩余一个,于是,老大吃掉这一个以后,再带走这堆桃的二分之一。
第二天,老二也看到了这堆桃,其想法和做法与老大一样,老三老四老五也和他们的兄长想到一块去了。
结果等老五吃完一个,带走一半以后,这堆桃还剩余11个。
请编程计算当初这堆桃共有多少个。
这个下题目明眼人一看便知,我们如果按兄弟吃桃搬桃的相反顺序倒推过去,就能知道当初桃子的总数。
其递推的公式是a[n-1]=a[n]*2+1。
递推的初始值是a[5]=11(又称边界条件),待求a[0]的值。
相信阅读本书到了此处的读者,很容易就能写出正确的程序。
作者在这里不过是想明确一下,递推算法不仅可以顺着推、也可逆着推的道理。
如果设输入数据为a[1]…a[n],输出结果为b[1]…b[n],则根据题意,我们应该不难得出下面的结论:1) a[k]:=b[k-1]+b[k]+b[k+1];2) a[1]和a[n]都会小于3;0 b[1]=0 b[2]=03) a[1]= 1 则b[1]=1 b[2]=0或b[1]=0 b[2]:=12 b[1]=1 b[2]=1有了上述三个结论后,程序算法便跃然纸上。
我们先根据a[1]得到b[1]和b[2]的值,然后递推出b[3]到b[n]。
在递推过程中,若递推出某个值b[k]>1或b[k]<0,如果a[1]=1,则交换b[1]和b[2]的值,然后再重新递推,若a[1]=0,2或已交换b[1],b[2],则问题无解。
递推算法是一个高效的算法,其时间复杂度是O(n)的。
不仅如此,它同时也是后面要学习的其它算法的基础,读者应该好好地把握它,多做这方面的习题积累经验。
递推算法的关键是认真分析题意,发现递推关系,正确写出递推公式,求得边界条件,然后用循环实现即可。
探究总结1.递推算法的基本形式,是指编程者让计算机循环求得一序列数值,而后一项的计算结果是由上一项或多项推导出来的。
有时,我们为求得一个数列的某一项,我们不得不从第一项开始,逐个计算前面每一项的值。
虽然这样做的效率不很高,但它能帮助我们解决许多实际问题。
2.无论是顺着还是逆着递推,其关键是递推公式是否正确,边界条件是否正确。
二者有一个出错。
则所有递推结果将都是错误的。
总结提高1、用一种长为2米,宽为1米的石板,给一条长为N米的长直道路铺面,石板可以竖放或横放,但不能裁剪,请求石板不同的铺设方法有多少种。
例如N=3时的铺法有以下几种,输出结束为3。
2、某生产企业,一年十二个月的生产利润与投资的比例均已预算出来,现假设企业从年从投入N万元,且下个月总是用上个月的本与利均作投资,请你编程求企业年底的总收入和纯利润和是多少。
例如,他们的一个预算如下:递归算法如果一个程序编程者不会使用递归与分治策略,那么其它的程序编辑技巧就无从谈起。
那么什么是递归与分治呢?要给它们下个定义可不容易,我们还是采用本书的编写特色,用实例来说明问题。
以前我们要求一个整数的阶乘,是采用循环相乘的方法进行的,程序的主要部分如下:s:=1;for I:=1 to n do s:=s*I;从这个算法我们不难看出,阶乘的递推关系为a[n]=n*a[n-1]。
边界条件a[1]=1。
采用递归算法的程序如下:若输入n=5,则上述程序的的执行过程描述如下:jc(5)=5*jc(4)=5*4*jc(3)=20*jc(4)=5*4*3*jc(2)=60*jc(2)=5*4*3*2*jc(1)=120*jc(1)=5*4*3*2*1=120函数在求值的过程中,不断调用自身,使数据规模逐渐缩小,直到边界条件有确定的值。
程序中没有看到循环,但具备循环的作用。
接着我们再来分析一个简单的递归例题。
图所示的情况,则输入为3和4,输出为4,长方形沿刻度线划分成一大三小四个正方形。
对于给定的长和宽a,b,编程求正方形的个数。
程序及其说明如下:Array若输入两数为5×7,则上述程序的执行过程描述如下:zhen(5,7)=1+zhen(5,2)=2+zhen(3,2)=3+zhen(1,2)=4+zhen(1,1)=5上述执行过程,计算机五次使用了自定义函数以获得最终解,我们称这个程序的递归深度为5。
由于计算机在处理递归时,要用到一种被称之为栈的存贮方式来存贮中间结果,而栈的深度、内存容量是有限的。
我们在解题时,如果让计算机处理的递归深度超过了限度,计算机就会有“栈溢出(error 202 stack overflow error)”的出错提示。
所以编程时,应尽可能将递归的深度缩小。
例如正方形一题可做下面的两个地方的优化,优化后的递归过程为:zhen(3,4)=4 div 3+zhen(3,1)=4 div 3+3 div 1zhen(5,7)=7 div 5+zhen(5,2)=7 div 5+5 div 2+zhen(2,1)=7 div 5+5 div 2+2 div 1相应的递归深度变为2和3。
改进前对应深度分别为4和5。
若输入数据较大,这个效果这个题目很容易让人想到,从顶点开始每次都选择左下或右下中两数中最大的一个往下走。
这就是我们邓上要学习的所谓贪心算法。
但读者看看上图中这样的一条路径:5,6,7,7,8,9,其和为42。
但另一条路径是5,6,4,8,9,14,其和为46。
递归算法的最大特点,是程序形式简单,思路清晰,能将复杂问题简单化。
很多程序算法书在讲到递归算法时,有一个典型例子就是“汉诺塔游戏”问题,请读者参看有关书籍。
这个例子将递归算法的优越性淋离尽致地表现出来。
但递归算法也有一个致命的弱点。
由于递归过程中,计算机要存贮大量的中间数据,既耗时,又耗时间。
有时还会进行很多重复运算。
例如:我们用递归方式求菲波拉契数列:令f(1)=1,f(2)=1,f(n)=f(n-1)+f(n-2)写成递归程序,大致如下:function fibnacci(n:integer);longint;beginif n<3 then beginfibnacci:=1;exit;end;fibnacci:=fibnacci(n-1)+fibnacci(n-2);end;这个过程并不算复杂,但计算机运行时却并不简单。
例如:我们要求fibnacci(8),计算过程描述如下,请读者自己分析重复计算的情况:f(8)=f(7)+f(6)=[f(6)+f(5)]+[f(5)+f(4)]={[f(5)+f(4)]+[f(4)+f(3)]}+{ [f(4)+f(3)]+[f(3)+f(2)]}=……上面三个例子都是递归函数的例子,其实过程同样可以递归。