搜索算法简单介绍:回溯法,深度优先搜索,广度优先搜索

首先简述一下题目 :
有一个正方形水池,长100,宽100, 池塘的正中心在坐标原点上,x轴向右为正,y轴向上为正,所以池塘的右上角坐标是(50,50)。池塘内分布着一些鳄鱼,鳄鱼的数目和坐标都已知(注1),邦德的最大跳跃距离也已知(注1)。邦德踩着鳄鱼头逐步跳上岸,问:最少的步数是多少?如果能跳出的话请给出一种跳法。

这道题乍一看很晕,待我建模给大家看。我们假设从原点O,第一次能跳到的鳄鱼编号为A1,A2,...,踩着A1能跳到的鳄鱼为B11,B12,....,踩着A2能跳到的鳄鱼为
B21,B22,......。也就是说,邦德能跳的路线可以由如下树性结构来表示。
           O
         / |         A1 A2 A3
       /|// /|// ....
    B11 B12 ......
   /|    |
C1111.........

很显然题目就是要求我们在这个树性结构中,找到一条路线,使得最末的一个点能够跳出水塘而已。

现在归结为:如何找一条这样的路径呢?最基础有两种思考方法!

方法一:一种就是我顺着一个枝一下子捅到底,直到跳上岸为止! 比如从O到A1再到B11再到C111,如果C111是一个死胡同,那么就退回B11,尝试C112,如果C112也不行的话,就退回B11,尝C113,如果B11所有的情况都试完还不行,那就退回A1,试B12....如此反复,直到邦德跳上岸为止。 这种方法有回溯的过程,因此叫做回溯法;这种搜索是向着树的深度方向进军的,因此叫做深度优先搜索法。

好了,到这里,我帮你问一个问题:如果邦德在几个鳄鱼头上跳圈圈怎么办?如果最初的选择方向不正确的话,是不是一直再耽误时间?

方法二:我们换个角度来考虑问题。我们假设邦德是分身有术,邦德拔一根头发吹口气,可以变出N个邦德来,这N个邦德还有同样的功能。  

现在从O出发有N1个鳄鱼头在邦德的跳耀范围内,好了,邦德拔一根头发变出N1个邦德来,这N1个邦德一下子跳到编号是A1~AN1个鳄鱼头上,然后A层的每一个邦德都又拔出若干头发,变出若干邦德,分别跳到B层的所有鳄鱼头上,.... ,继续跳,继续跳,继续跳。。。终于有一个邦德的曾孙子辈的邦德跳上了岸。邦德瞧准它这一个脉系的路线,依次跳过,于是就跳上了岸。  

抽象成树性结构就是说,从O扩展全部的A层节点,再从全部的A层节点扩展B层节点,这样出现的第1个能够节点跳上岸的节点,极为所求。

这种做法是一扩展为首要步骤得,所以叫做广度优先搜索法。


好了,跳法已经明确,现在看看具体的实现步骤吧。
1>怎么选择某一节点的下层节点?也就是邦德能跳得下一步有多少种跳法,怎样选择
2>什么时候搜索停止,也就是邦德跳上岸的终结条件是什么。

1> 假设A(x1,y1),目的节点B(x2,y2),邦德能够跳得最大距离是L?
那么选择B节点的约束条件是:sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))<l

2> 判断A(x1,y1)是否能够跳到岸上就是看
if ( (50-abs(x1))<l || (50-abs(x2))<l ) { //.. 可以跳到岸上
}

存储节点可以定义一个struct结构,只要包含x,y坐标就行了。只有用这个结构的数组或链表就可以了。
做两个指针纪录链表得偏移。

阅读更多
个人分类: 算法/程序设计/POJ
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭