收藏 分享(赏)

搜索相关算法学案274177.doc

上传人:dreamzhangning 文档编号:2689512 上传时间:2018-09-25 格式:DOC 页数:6 大小:58.50KB
下载 相关 举报
搜索相关算法学案274177.doc_第1页
第1页 / 共6页
搜索相关算法学案274177.doc_第2页
第2页 / 共6页
搜索相关算法学案274177.doc_第3页
第3页 / 共6页
搜索相关算法学案274177.doc_第4页
第4页 / 共6页
搜索相关算法学案274177.doc_第5页
第5页 / 共6页
点击查看更多>>
资源描述

1、1搜索相关算法(二)三深度优先搜索深度优先搜索所遵循的搜索策略是尽可能“深”的搜索树。在深搜中,对于当前发现的结点,若它还存在以此结点为起点而未探测到的边,就沿此边继续搜索下去。若当前结点的所有边都已被探寻过,则回溯到当前结点的父结点,继续上述的搜索过程直到所有结点都被探寻为止。深度优先搜索在树的遍历中也称作树的先序遍历。深搜递归算法:procedure try(depth:longint,)var i:longint,;beginif depth目标深度 then begin 输出方案;exit end;for i:=depth 深度可能决策范围 do beginif 决策 i 符合展开条件

2、 then begin记录决策 i; try(depth+1); 删除决策 i;end;end;end;主程序调用:try(1);说明递归形式的程序符合思维习惯,编写起来较容易,但由于递归过程的调用借助较慢的系统栈空间传递参数和存放局部变量,故降低了执行效率。我们可以模拟递归,使用数组存放堆栈数据,在管理指针和每层决策上不如递归容易编程,但一旦熟悉了程序框架,调试起来要比递归程序方便。深搜非递归算法:varstack:array1maxsize of statetype; depth:longint; begin程序读入数据并初如化; depth:=0;repeatif 可以展开 then b

3、egindepth:=depth+1; 在 stackdepth中记录第一种决策; if depth=目标深度 then 输出方案; endelse if 可以选择新决策 then 改写 stackdepth为新决策 else begin 消除当前深度的尝试对其他变量的影响; depth:=depth-1; end;until depth=0;程序终止化;end.例 1 简单的背包问题。2设有一个背包,可以放入的重量为 s。现有 n 件物品,重量分别为W1,W2,Wn ,Wi(1=s thenbegin try:=false;exit;end;elsetry:=true;end;procedu

4、re search(v:integer); v 表示第 v 个位置var i:integer;3beginif vn then exit; 若 v 超界,一个排列完成,本次选择物品方案不成功,退出for i:=0 to 1 do 在第 v 个位置上分别放 0 到 1if try(v, i) then 判断所选物品之和是否大于等于 s,否则处理第 v+1 个位置begin xv:=i; search(v+1);end;end;begininit;search(1);end.小结 深度搜索有一定固定模式,但其变种还很多,就其实质来说是“怎样构造一棵用来搜索的树(tree),然后对这棵树(tree)

5、进行高效率的剪枝” ,更重要的是对题目描述的问题建立科学合理的数学模型。深搜算法要点(1)结点定义:即如何描述问题的状态以及状态间的关系。 (2)边界条件:即在什么情况下程序不再递归下去。 (3)搜索范围:在当前状态下不满足边界条件的情况下,应如何设计搜索的范围。通常是指设定循环变量的初值和终值。 (4)约束条件:当前扩展出一个子结点后应满足什么条件方可继续递归下去。 (5)恢复递归前状态:如果扩展子结点的过程有全局变量参与,则回溯前必须恢复其递归前的值。四广度优先搜索广搜在树中又叫按层次遍历。对于树而言,宽度优先搜索的思路可以描述为:访问根结点,依次访问根结点的每一个子结点(第二层结点) ,

6、再通过这些结点访问第三层结点。宽搜与深搜相比,时间复杂度是相同的,不同的仅仅在于结点访问的顺序不同。有些问题上,比如求最优解,宽搜比深搜好。如倒酒问题:有三个酒杯,容量分别为 4、3、1ml ,开始时在容量为 4ml 的酒杯中装满酒,另外两个酒杯为空杯,怎样用这三个酒杯以最少的倒酒次数分出 2ml 的酒来?我们将三个酒杯分别编上号,容量为 4 的杯子为 1 号,容量为 3 的杯子为 2 号,容量为 1 的杯子为3 号,用三个酒杯中的酒的数量表示当前状态,共有六种不同的倒酒方法,依次为从 1 倒向2,从 1 倒向 3,从 2 倒向 1,从 2 倒向 3,从 3 倒向 1,从 3 倒向 2。如果用

7、深搜,回溯的条件为当前状态在前面曾经出现过,继续搜索将成死循环。下面两个图分别描述了深搜与宽搜的全过程。4 0 0121 3 00 3 13 0 10 3 1 4 0 0 3 1 01 3 0 2 1 1132112 31 3212 134 0 01 3 0 3 0 10 3 1 4 0 0 1 2 112 1313 21234入门例题 :有 10 升油在 10 升的容器中,另有两个 7 升和 3 升的空容器,要求用这三个容器倒油,使得最后在 10 升和 7 升的容器中各有 5 升油,问最少的倒油次数是多少?输入:第 1 行 3 个整数,表示容器的容量;第 2 行为油桶的初始状态;第 3 行为

8、油桶的目标状态。输出:倒油的次数vara:array13 of integer; 每个容器的容量x:array11000,13 of shortint; 存放已经出现过的状态y:array11000 of integer; 存放树(tree)的前缀层数,即当前倒油次数b:array13 of integer; 目标状态c:array13 of integer;p1:integer;p2:integer;i,j,t:integer;pt:boolean;procedure init;beginassign(input,xx1.txt);reset(input);readln(a1,a2,a3);

9、 readln(x1,1,x1,2,x1,3); 读取初始状态readln(b1,b2,b3); 读取目标状态close(input);end;procedure out;beginwriteln(yp1+1);halt;end;function find:boolean;var i:integer;beginfor i:=1 to p2 doif (c1=xi,1) and (c2=xi,2) and (c3=xi,3) thenbegin find:=false;exit;end;find:=true;5end;begininit;fillchar(y,sizeof(y),0);p1:=1

10、;p2:=1;while p1j thenbeginfor t:=1 to 3 doct:=xp1,t;pt:=false;if ci+cj=0) and (pt=false) then只能倒一部分beginci:=ci-(aj-cj);cj:=aj;pt:=true;end;if pt thenbeginif (c1=b1) and (c2=b2) and (c3=b3) thenout; 到达目标输出if find then 判重begininc(p2); 队列入列操作for t:=1 to 3 doxp2,t:=ct; 取得当前树的扩展层数,即:倒油次数yp2:=yp1+1;end; e

11、nd;end;inc(p1); 队列出列操作end; end.宽搜一般算法:(其中 max 为产生子结点的规则数)6program BFS;初始化,初始状态存入 state 表中:队列首指针 head:=0; 尾指针 tail:=1;repeathead 后移一位: head:=head+1; 指向待扩展结点for i:=1 to max dobeginif 子结点符合条件 then begintail:=tail+1; 新结点入队;if 新结点与原已产生的结点重复 then 删去该结点(取消入队,tail 减 1)else if 新结点是目标结点 then 输出并退出;endend;unitl head=tail;练习 1给出一个由 1,2,3,4,5,6 组成的 6 位数,相邻的两个数字可以交换位置,问最少经过多少次交换,可以到达另一个目标 6 位数。例如:对于 123456,最少经过两次交换,可以变成 231456。练习 2一个农夫带着一头狼、一只羊和一捆草,要借助一条小船过河,船只能由农夫自己摆渡,并且船最多只能再装载狼、羊、草中的任意一个。但是,狼与羊、羊与草不能单独呆在一起。请给出一种摆渡方案,使农夫、狼、羊、草都能到河对岸。一个大于等于 2 小于等于 10 的 9 次方的数,转化为 N 个自然数的乘积,输出所有方法。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报