浅谈dfs&bfs

dfs(深度优先搜索)

bfs(广度优先搜索)

前言

作为初学者,可能会想,搜索吗,就是作用在图上啊,树上什么的算法。其实,搜索(这里主要说dfs和bfs),就是以一种特定方式,在大多数场景寻找真正想要结果的方式。而dfs就是以一种现已一种单一方式走到黑,然后通过回溯等得到答案的过程。而bfs则是先看有多少种方式可以走,然后先记录每一种方式,在一一按这种方式一层一层遍历,直到得到最后结果。这两种搜索大体上没什么差别,都是搜索出所有可能满足自己的答案而已。有的人可能会说,bfs适合求最短路径,dfs适合求所有答案,其实,两个都可以相互转化(这里不多说,其实我也不怎么懂,哈哈~),只不过方便与否的问题罢了。

下面就对这两种经典搜索进行简单探讨。

dfs(深度优先搜索)

模板:

void bfs(){
	if:(...){//需要的结果
		...
	//做出操作
	return;//结束 
	} 
	...
	dfs();
	...//具体要怎么搜索 
} 

这就是走到黑方式,就像对123进行全排列,123,132,213,231,312,321;

按照顺序排列就是方式,然后逐个改变。

多说这种无益,来一道最简单的bfs的题目吧:

有一款游戏叫做《绝地求生:大逃杀》。

绝地求生,是一款开放世界策略射击游戏,采用虚幻4引擎制作。 是一款大逃杀类型的游戏,每一局游戏将有100名玩家参与,他们将被投放在绝地岛(battlegrounds)的上空,游戏开始跳伞时所有人都一无所有。 游戏展开的方式是:玩家赤手空拳地分布在岛屿的各个角落,利用岛上多样的武器与道具。 随着时间的流逝,岛上的安全地带越来越少,特定地区也会发生轰炸的情况,最终只有一人存活获得胜利。游戏的每一局比赛都会随机转换安全区,这样玩家的很新鲜与紧张感会更加强烈。

小东同学玩游戏也坚决不忘算法的学习,有一天,他面临了这样的情况,小东要前往安全区,他决定冒险通过一片大平原,虽然跑向两边的山上更安全,但是时间来不及了。在小东同学奔跑的过程中,浑然不知两边的山上各有一个人趴在那里埋伏猎物,他们同时发现小东,同时开枪!小东意识到危险了!伴随了若干声枪声,砰砰砰!小东已经倒地了…

小东挂掉之前一秒,意识到了一件事,两边的人同时开枪,那么我又多少种中弹顺序呢?比如我有100血,而一个人用冲锋枪每发子弹能伤害我30血,另一个人用步枪每发子弹能伤害我45血,那导致我死亡的中弹顺序可能是,30 30 30 45,也可能是 45 45 30,也有可能是45 30 45,等等。当然,血量小于或等于0都算被击倒。

同时要注意,如果两人每次对自己造成的伤害是相同的,但仍被看作不同的死亡顺序,比如玩家有100血量,左右两边的人每次能造成50血量的伤害,那么答案为4,情况分别为:

50 50(左边敌人打中了两枪)。

50 50(右边敌人打中了两枪)

50 50(左边敌人开了第一枪)

50 50(右边敌人开了第一枪)

输入

本题有多组测试数据。每组占一行,由三个正整数m n hp组成(10=<m<hp<90,10<=n<hp<90)。m代表左边的敌人每次对玩家造成的伤害,n代表右边的敌人每次对玩家造成的伤害,hp代表玩家的血量。

输出

对于每组输入数据,输出一行,结果为玩家有多少种死亡顺序,即中弹顺序。

样例输入

45 30 100
50 50 100
12 23 80

样例输出

9
4
34

思路:看题意是求出所有方式,所以用dfs比较方便,然后,走到黑,先以第一种方式减血(第一个例子,-45,-45,-45。。。),然后就回溯,继续操作,看代码:

//绝地求生之死亡顺序
#include<iostream>
using namespace std;
int ans=0,l,r,hp;
void dfs(int hp,int l,int r){
	if(hp<=0){
		ans++;
		return;
	}
	dfs(hp-l,l,r);
	dfs(hp-r,l,r);
} 
int main(){
	while(cin>>l>>r>>hp){
		dfs(hp,l,r);
		cout<<ans<<endl;
		ans=0;
	}
	
}

 

下面就来看bfs:

bfs(广度优先搜索)

模板:

void bfs(){
	if(){
		return;//首先判断当前位置是否为结果 
	}
	while(){
		...//循环每一种方试直到最后的结果 
	} 
	
	return ; 
} 

 

对于bfs,用得最多的试队列,来插入(记录方法)与弹出(此方法遍历完毕)来进行搜索, 最经典的迷宫问题(求最短路径):

平面迷宫

时间限制: 1 Sec  内存限制: 128 MB

 

题目描述

老王同学深陷一个迷宫,他现在想要逃出去。迷宫 是这样的,在m行n列的矩阵当中,“.”表示可以通过的道路,“#”表示墙,是障碍物所以不能通过。迷宫中S代表起始点,E代表出口。老王每次只向上、向下、向左、向右移动一个单位距离,每次移动一个距离话费的时间是1分钟。请问老王最少花多少时间可以离开迷宫,或者根本就不能离开迷宫?

输入

本题有多组测试数据,对于每组测试数据:

两个整数mn表示m行n列的迷宫,0<mn<=100

接下来是m行n列的迷宫,其中S表示入口,E表示出口,#表示墙,.表示通路。

输出

如果老王逃出去话费X分钟,则输出:

Escaped in x minute(s).

如果老王不能逃出去,则输出:

Trapped!

样例输入

3 3
S..
.#.
..E

3 3
S#.
.#.
.#E

样例输出

Escaped in 4 minute(s).
Trapped!

 

思路也不必多说,搜索所有路径,找到最短的,代码如下:

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
char map[101][101];
int n,m;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int v[101][101],d[101][101];
queue <char> q;
void bfs(int x,int y){
	while(q.size()){
	char tq=q.front();
	q.pop();
	if(tq=='E')	
		break;
	for(int i=0;i<4;i++){
		int tx=x+dir[i][0];
		int ty=y+dir[i][1];
		if(map[tx][ty]=='.'&&v[tx][ty]==0&&tx>=0&&tx<n&&ty>=0&&ty<m){
			q.push(map[tx][ty]);
			d[tx][ty]=d[x][y]+1;
			v[tx][ty]=1;
		}
	}
	
	}
} 
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		memset(v,0,sizeof(v));
		memset(d,0,sizeof(d));
		int ex,ey,sx,sy;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++){
				cin>>map[i][j];
				if(map[i][j]=='S'){
					sx=i;
					sy=j;
					q.push(map[i][j]);
					v[i][j]=1;
				}
				if(map[i][j]=='E'){
					ex=i;
					ey=j;
				}
				
			}
		bfs(sx,sy);
		if(d[ex][ey]==0)
		cout<<"Trapped!"<<endl;
		else
		cout<<"Escaped in "<<d[ex][ey]<<" minute(s)."<<endl;
				
	}
	
	
}

可能会有错哦,好久以前写的,不知道是对的还是错的,但知道方式与思路就行!

其实dfs与bfs都大相径庭,所以,当你用熟练了,几乎都能互用,只是代码多少的问题而已!

 

 

点赞