递归与深度优先搜索算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2014年 赵宗昌
第一步:先借助3柱把1柱上面的n-1个盘子移动到2柱上。
第二步:然后再把1柱最下面的一个盘子移动到3柱上。
第三步:再借助1柱把2柱上的n-1个盘子移动到3上。
2014年 赵宗昌
procedure move(i,x,y,z:integer); //把x柱上的编号1到i的i个盘子借助y移动到z上 begin if i=1 then writeln(1,' : ',x,'-->',z) else begin move(i-1,x,z,y); writeln(i,' : ',x,'-->',z); move(i-1,y,x,z); end; end;
2014年 赵宗昌
6 Hanoi(汉诺塔)问题
问题的提出: Hanoi塔由n个大小不同的圆盘和3根木柱1,2,3组成。开始时,这n个 圆盘由大到小依次套在1柱上,如图所示。
现在要求用最少的移动次数把1柱上n个圆盘按下述规则移到3柱上: (1) 一次只能移一个圆盘; (2) 圆盘只能在3个柱上存放; (3) 在移动过程中,不允许大盘压小盘。
【例3】求最大公约数 输入a和b,输出a和b的最大公约数。 如: 输入:100 75 输出:25
2014年 赵宗昌
欧几里德算法(又称辗转相除法)
用于计算两个正整数a,b的最大公约数。 一般把a和b的最大公约数记为gcd(a,b)。 公式: gcd(a,b)=gcd(b,a mod b) gcd(a,0)=a 如:gcd(100,75)=gcd(75,25)=gcd(25,0)=25;
请编程描述移动的过程。 。
2014年 赵宗昌
N=1 1 : 1-->3
N=2 1 : 1-->2 2 : 1-->3 1 : 2-->3
N=3 1 : 1-->3 2 : 1-->2 1 : 3-->2 3 : 1-->3 1 : 2-->1 2 : 2-->3 1 : 1-->3
N=4 1 : 1-->2 2 : 1-->3 1 : 2-->3 3 : 1-->2 1 : 3-->1 2 : 3-->2 1 : 1-->2 4 : 1-->3 1 : 2-->3 2 : 2-->1 1 : 3-->1 3 : 2-->3 1 : 1-->2 2 : 1-->3 1 : 2-->3
2014年 赵宗昌
【方法1】 var a,b,r:longint; begin readln(a,b); while b>0 do begin r:=a mod b; a:=b; b:=r; end; writeln(a); end.
2014年 赵宗昌
【方法2】递归 var a,b:longint; function gcd(a,b:longint):longint; begin if b=0 then exit(a); exit(gcd(b,a mod b)); end; begin readln(a,b); writeln(gcd(a,b)); end.
2014年 赵宗昌
4.读程序写结果
• var • n:longint; • procedure f(n:longint); • begin • if n>0 then • begin • f(n div 2); • write(n mod 2); • end; • end; • begin • readln(n); • f(n); • End.
2014年 赵宗昌
【例2】:计算n!
可用公式如下: f(n)=1 f(n)=n*f(n-1)
当 n=1 时 当n>1时
递归的执行过程
2014年 赵宗昌
var n:integer; function f(i:integer):integer; begin if i=1 then f:=1 else f:=i*f (i-1); end; begin readln(n); writeln(f(n)); end.
n=20
# include <iostream> # include <cstdio> using namespace std; void dfs(int i){ if (i>0) { dfs(i/2); printf("%d",i % 2); } } int main() { int n; scanf("%d",&n); dfs(n); return 0; }
2014年 赵宗昌
最少的移动次数
第一步:先借助3柱把1柱上面的n-1个盘子移动到2柱上,所需的移 动次数为f(n-1)。 第二步:然后再把1柱最下面的一个盘子移动到3柱上,只需要1次 盘子。 第三步:再借助1柱把2柱上的n-1个盘子移动到3上,所需的移动次 数为f(n-1)。
由以上3步得出总共移动盘子的次数为:f(n-1)+1+ f(n-1)。 所以:f(n)=2 f(n-1)+1
2014年 赵宗昌
方法2:
var a:array[1..10] of longint; i:longint; begin a[10]:=1; for i:=9 downto 1 do a[i]:=(a[i+1]+1)*2; writeln(a[1]); end.
第3讲 递归与深度优先搜索算法
一. 递归
2014年 赵宗昌
2014年 赵宗昌
"从前有座山山上有座庙,庙里有个老和尚,老和尚 在给小和尚讲故事:
"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
……
"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
f(n)= 2n-1
2014年 赵宗昌
2014年 赵宗昌
2014年 赵宗昌
方法1:
var n:longint; function f(i:longint):longint; begin if i=10 then exit(1); exit((f(i+1)+1)*2); end; begin n:=f(1); writeln(n); end.
Function 函数名(参数):类型; Procedure 过程名()参数;
Int 函数名(参数); Void 函数名(参数);
2014年 赵宗昌
过程
过程
过程
……
过程
递 归 结 束
2014年 赵宗昌
【例1】猴子吃桃问题
小猴摘了很多桃子。 第一天吃了一半又多吃一个; 第二天又吃掉剩下的一半再多吃一个; …… 以后每天都是吃前一天剩下的一半再多一个。 如此下去,到第十天恰好还剩一个桃子。 问第一天小猴摘了多少桃子?
这就是递归
2014年 赵宗昌
递归的概念:
一个过程(或函数)直接或间接调用自己 本身,这种过程(或函数)叫递归过程(或函数 ). 满足某个条件后递归终止。
2014年 赵宗昌
递归的关键:
1.确定递归公式(关系) 2.确定边界(终止)条件
当递归没有到达边界终止时,继续向前,直至边界才返回。
2014年 赵宗昌
2014年 赵宗昌
5.递归的层数
var n:longint; procedure dfs(i:longint); begin writeln(i); dfs(i+1); end; begin dfs(1); end. # include <iostream> # include <cstdio> using namespace std; void dfs(int i){ printf("%d\n",i) ; dfs(i+1); } int main() { dfs(1); return 0; }
2014年 赵宗昌
var n:integer; function f (i:integer):integer; begin if i=1 then exit(1); exit(i*f (i-1)); end; begin readln(n); writeln(f (n)); end.
2014年 赵宗昌
2014年 赵宗昌
关系:
第i天的桃子=(第i+1天的桃子 +1)*2 i=10时 ,有1只桃子。
f(10)=1 f(i)=2*(f(i+1)+1) 求 f(1)=?
2014年 赵宗昌
方法1:
var n:longint; function f(i:longint):longint; begin if i=10 then f:=1 else f:=(f(i+1)+1)*2; end; begin n:=f(1); writeln(n); end.
2014年 赵宗昌
# include <iostream> # include <cstdio> using namespace std; int f(int i){ if (i==10) return 1; return 2*(f(i+1)+1); } int main() { cout<<f(1); return 0; }
readln(n); move(n,1,2,3);
2014年 赵宗昌
ຫໍສະໝຸດ Baidu
# include <iostream> # include <cstdio> using namespace std; void move(int i,int a,int b,int c){ if (i>0) { move(i-1,a,c,b); printf("%d : %d -> %d\n",i,a,c); move(i-1,b,a,c); } } int main() { int n; scanf("%d",&n); move(n,1,2,3); return 0; }