两种简单的搜索算法

来源:互联网 发布:李连杰人品 知乎 编辑:程序博客网 时间:2024/05/16 07:51

搜索算法是图论中常用到的算法,这里介绍两种常用的算法。这两种算法都是是以队列为基础的。

最简单的搜索方法:迷宫搜索,这种搜索方法是从当前位置出发,向四周辐射,直到搜索到目标位置,这种搜索方法的特性是:每向前推进一步花费的步骤数(时间)是相同的,所以这种搜索方法的实现非常的简单,我们只需要将走过的地方标记,然后将符合条件的待搜索部分压入搜索队列即可。这里我们只需要普通队列即可。(队列的构造及使用方法)

下面我们以下面的一个搜索图为例,演示这种基本的搜索方法。

我们从start开始搜索,到end结束。其中青绿色方格不可通过,无颜色的方格可以通过,

其中每移动一个方格,需要花费一个单位时间,下面我们来计算该过程花费的时间。

1

2

3

4

5

6

7

8

9

10

11

start

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

end

下面我们用字符来模拟上面的图表。S代表startE代表endO代表无色方格,即可通过方格,N代表不可通过表格。

OOOOO

ONNNN

OSOON

OONON

OONON

OONON

OONOE

算法实现过程:用一个结构体来描述每个方格(搜索节点)的性质,即位置坐标和时间,同时建立结构体类型的一个搜索队列,把开始位置压入首先压入搜索队列并把该位置标记为‘N’,然后向四周搜索,把符合条件的元素载入搜索队列接着把载入队列的元素标记为‘N’(已经搜索过),直到搜索到目标元素位置为止。

CODE:

#include<iostream>#include<string>#include<queue>using namespace std;int x1,y1,x2,y2;//记录搜索起始位置的坐标char map[7][5];//记录需要搜索的图int dir[4][2]={1,0,-1,0,0,1,0,-1};//控制前后左右四个方向struct node//结构体用来描述每一个压入队列中元素的性质{int x,y,time;//记录每个表格的位置和处于该表格时的时间};bool judge(int x,int y) //判断该表格处的元素是否能被搜索{if(x>=0&&x<7&&y>=0&&y<5&&map[x][y]!='N')return true;elsereturn false;}int BFS(){queue<node>q;//声明以结构体为类型的队列qnode cur,next;//当前位置,下一个位置int x,y,i;cur.x=x1;cur.y=y1;cur.time=0;      //把开始位置处的方格首先载入方格map[x1][y1]='N';q.push(cur);while(!q.empty()){cur=q.front();q.pop();if(cur.x==x2&&cur.y==y2)     //搜索到目标return cur.time;next.time=cur.time+1;for(i=0;i<4;i++)             //当前位置下向四周搜索{next.x=x=cur.x+dir[i][0];next.y=y=cur.y+dir[i][1];if(judge(x,y)){q.push(next);map[x][y]='N';}}}return -1;}int main(){int i,j;for(i=0;i<7;i++)//读入搜索图cin>>map[i];for(i=0;i<7;i++)//得到搜索起始位置的坐标for(j=0;j<5;j++){if(map[i][j]=='S'){x1=i;y1=j;}if(map[i][j]=='E'){x2=i;y2=j;}}int ans;ans=BFS();cout<<ans<<endl;return 0;}


 

通过这个例子我们可以了解到这种搜索方法好像是地毯式的搜索,在搜索域内所有可搜索的元素(距离不超过起始位置的距离)都可以得到一个时间的记录。在上面代码的基础上稍作改动即可得到这张结果表。

下面来介绍 一种稍微复杂的搜索方法,上面的搜索例子里,每次移动一次花费的时间是一样的,如果移动到不同的方向花费的时间不等该怎么办呢?这就要用到优先队列。仍以具体的实例的为例。

问题描述:

4 5

OONOO

SNNNE

OOOOO

NOOON

给你一个n*m的方格,其中S代表你的位置,E代表你要到达的位置,N代表一堵墙,通过N你需要花费一个单位时间清理墙,一个单位时间通过该位置(即共2个单位时间);O代表你可以花费一个单位时间通过,请输出到达该地的最少时间?

算法分析:

实现这个目标,我们只需以上面那个例子为基础处理每步移动时间的不同即可,这里我们使用优先搜索队列可以解决。(优先队列的构造方法及使用)

Code

 

#include<iostream>#include<queue>#include<string>using namespace std;char map[100][100];int n,m;int x1,y1,x2,y2;int dir[4][2]={0,1,0,-1,1,0,-1,0};struct node{friend bool operator <(node a,node b){return a.time<b.time;}int x,y,time;};int BFS(){int x,y,i;priority_queue<node>q;node cur,next;cur.x=x1;cur.y=y1;cur.time=0;q.push(cur);map[x1][y1]='#';while(!q.empty()){cur=q.top();q.pop();for(i=0;i<4;i++){next.x=x=cur.x+dir[i][0];next.y=y=cur.y+dir[i][1];if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='#'){if(x==x2&&y==y2)return cur.time;if(map[x][y]=='O')next.time=cur.time+1;if(map[x][y]=='N')next.time=cur.time+2;q.push(next);map[x][y]='#';}}}return -1;}int main(){int i,j;while(cin>>n>>m){for(i=0;i<n;i++)cin>>map[i];for(i=0;i<n;i++)for(j=0;j<m;j++){if(map[i][j]=='S'){x1=i;y1=j;}if(map[i][j]=='E'){x2=i;y2=j;}}int ans;ans=BFS();cout<<"The min_time: "<<ans<<endl;}   return 0;}


原创粉丝点击