深搜和广搜 (DFS & BFS)

转载地址:http://yes2.me/archives/424

这里介绍深度搜索和广度搜索的基本知识,适合学习搜索算法的初学者,如果是高手请手下留情!

一、总体介绍

搜索算法是利用计算机的高性能来有目的的穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。搜索过程实际上是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的节点的过程。通俗点说,搜索说枚举所有可能答案,然后找出最佳答案的一个方法。

下面的说的深度搜索和广度搜索,都是枚举可能答案,但是遍历的顺序不一样,所以在运用在不同的地方。

二、深度优先搜索(DFS)(Depth-First Search)

正如名字上的不同那样,深度优先搜索就是尽可能的“深”的图。

如右图所示,深度搜索的顺序应当是:

a->b->d(没有路了,回溯到a)->c->e->g(没有路了,回溯到e)->h(没有路了,回溯到c)->f(本次搜索结束)

好了,了解什么是DFS后我们来看看如何描述这个算法:

例题1:HDU1010Tempter of the Bone 题目大意讲的是有一只小狗被困在迷宫里面了,迷宫用S(起点)、D(出口)、X(墙)、.(过道)组成,小狗每秒移动一格,出去的条件的在正好T秒时走到D处,而且每个点上只能呆一秒,不能走已经走过的路。

代码:

# include 
# include 
# include 
using namespace std;
char map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; 

void dfs(int si,int sj,int cnt)
{    int i,temp;
   if(si>n||sj>m||si< =0||sj<=0) return;
   if(cnt==t&&si==di&&sj==dj)    escape=1;
   if(escape) return; 

   temp=(t-cnt)-abs(si-di)-abs(sj-dj);
   if(temp<0||temp&1) return;
   for(i=0;i<4;i++){
      if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
	  {
         map[si+dir[i][0]][sj+dir[i][1]]='X';
         dfs(si+dir[i][0],sj+dir[i][1],cnt+1);
         map[si+dir[i][0]][sj+dir[i][1]]='.';
      }
   }
   return;
} 

int main()
{
	int i,j,si,sj;
	while(cin>>n>>m>>t)
	{
	  if(n==0&&m==0&&t==0) break;
	  int wall=0;
	  for(i=1;i< =n;i++)
         for(j=1;j<=m;j++)
		 {
            cin>>map[i][j];
            if(map[i][j]=='S') { si=i; sj=j; }
            else if(map[i][j]=='D') { di=i; dj=j; }
            else if(map[i][j]=='X') wall++;
         }
       if(n*m-wall< =t)
	   {
		   cout<<"NO"<<endl; continue;="" }="" escape="0;" map[si][sj]="X" ;="" dfs(si,sj,0);="" if(escape)="" cout<<"yes"<<endl;="" else="" cout<<"no"<<endl;="" return="" 0;="" <="" pre="">

三、广度优先搜索(BFS)(Breadth-First Search)

广度优先搜索其实也很简单,只不过遍历的顺序不同罢了,也是上面那副图,广度优先搜索顺序是:

a->b->c (这层没有节点了,拓展到下层) -> d -> e -> f (这层没有节点了,拓展到下层) -> g - >h

从这个顺序上就很容易看出DFS和BFS的区别。不过虽然看似小小的不同,其效果可是大大的不同的,BFS一般又在寻找“最”什么的问题上。废话少说,还是先来一个例题。

例题2:HDU1253胜利大逃亡 题目中文的,有图片,所以这里就不描述。

这个题目如果用DFS也可是得出答案,但是如果用DFS做要搜索完全部的路,才能找到最短的时间,而BFS是一层一层展开的,所以只要碰到出口,那必定是用时最少的一条。节约了很多时间,讲到这里,大家是否对搜索有了初步的了解了?

代码(队列实现):

#include
#include
using namespace std;
#include
int di[6][3]={{0,0,1},{0,1,0},{1,0,0},{0,0,-1},{0,-1,0},{-1,0,0}};
int map[101][101][101];
int A,B,C,T;
struct node
{
	int x;
	int y;
	int z;
	int t;
	node(int x,int y,int z,int t)
	{
		this->x=x;
		this->y=y;
		this->z=z;
		this->t=t;
	}
};
void bfs()
{
	queue q;
	q.push(node(0,0,0,0));
	map[0][0][0]=1;
	while(!q.empty())
	{
		node now=q.front();
		q.pop();
		int tx,ty,tz;
		for(int i=0;i<6;i++)
		{
			tx=now.x+di[i][0];
			ty=now.y+di[i][1];
			tz=now.z+di[i][2];
			if(tx>=0&&tx=0&&ty=0&&tz<c &&map[tx][ty][tz]!="1)" {="" if(tx="=A-1&&ty==B-1&&tz==C-1&&now.t+1<=T)" printf("%d
",now.t+1);="" return;="" }="" q.push(node(tx,ty,tz,now.t+1));="" map[tx][ty][tz]="1;" printf("-1
");="" int="" main()="" t;="" scanf("%d",&t);="" while(t--)="" scanf("%d%d%d%d",&a,&b,&c,&t);="" for(int="" i="0;i<A;i++)" j="0;j<B;j++)" k="0;k<C;k++)" scanf("%d",&map[i][j][k]);="" bfs();="" return="" 0;="" <="" pre="">


原文地址:https://www.cnblogs.com/dengshiwei/p/4258633.html