BFS/DFS算法介绍与实现(转)
广度优先搜索(Breadth-First-Search)和深度优先搜索(Deep-First-Search)是搜索策略中最经常用到的两种方法,特别常用于图的搜索.其中有很多的算法都用到了这两种思想,比如:Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。
BFS的思想:
从一个图的某一个顶点V0出发,首先访问和V0相邻的且未被访问过的顶点V1、V2、……Vn,然后依次访问与V1、V2……Vn相邻且未被访问的顶点。如此继续,找到所要找的顶点或者遍历完整个图。
由此可以看出,用BFS进行搜索所搜索的顶点都是按深度进行扩展的,先找到到V0距离为1的所有顶点,然后找到距离V0为2的顶点……所以BFS所搜索到的都是最短的路径。
由于要将距离V0为d(d>0)的且未被方位的点都记录起来,我们采用队列这种数据结构。队列的特点是先进先出(FIFO),从某个顶点出发,记此顶点已访问标记,然后依次搜索和此顶点相邻的且未被访问的顶点,将其加入队列,并置已访问标记,重复此步骤,直到找到需要搜索的顶点或者所有的顶点都被访问为止。
算法的基本流程如下:[code]
procedure BFS(i);
begin
write(i);
visited[i]:=true;
insert(q,i);{q是队列,i进队}
repeat
k:=delete(q);{出队}
for j:=1 to n do
if (a[k,j]=1) and (not visited[j]) then
begin
write(j);
visited[j]:=true;
insert(q,j);
end;
until 队列q为空;
end.
[/code]DFS的思想:
顾名思义,深度优先搜索所遵循的策略就是尽可能“深”的在图中进行搜索,对于图中某一个顶点V,如果它还有相邻的顶点(在有向图中就是还有以V为起点的边)且未被访问,则访问此顶点。如果找不到,则返回到上一个顶点。这一过程一直进行直到所有的顶点都被访问为止。 DFS可以搜索出从某一个顶点到另外的一个顶点的所有路径。 由于要进行返回的操作,我们采用的是递归的方法。
其基本算法流程如下:[code]
procedure DFS(V0)
begin
visite(V0);
visited[V0]=true;
for j:=1 to n do
if (a[V0,j]=1) and (not visited[j]) then
DFS(j);
end;
[/code]//采用邻接表为存储结构[code]
void dfs(algraph *g,int v)
{
arcnode *p;
visited[v]=1; //置已访问标记
cout< p=g->adjlist[v].firstarc; //p指向顶点v的第一条弧的节点
while(p!=NULL){
if(visited[p->adjvex]==0)//若p->adjvex顶点没有访问,递归进行访问
dfs(g,p->adjvex);
p=p->nextarc; //p指向顶点v的下一条弧的弧头节点
}
}
[/code]下面举一个具体的例子来说明一下BFS和DFS的应用。
题目描述:给一个M×N的迷宫,里面有宝藏('o'表示,此位置可走)、墙('#'表示,是不能走的位置)和空位 置 ('.'表示,可走),现在要求从迷宫的左上角出发,在最短的步数里面找到K个宝藏(K给定),每一步可以走当前位置的上下左右四个相邻的位置.
现给定迷宫和K(K<=迷宫中o点的数目),返回最小的步数,不能满足要求则返回-1.
Example:
1)
.....
o....
o....
o....
...o.
3
Returns: 3 (从左上角直接往下走三步即可)
2)
.#...
#....
...oo
...oo
...oo
1
Returns: -1
because can't move from the starting location.
3)
...o.
o..o.
.....
..oo.
.....
4
Returns: 7
4)
....#
.##o#
.##oo
o##.#
....#
4
Returns: 12
解答:
此题是topcoder的一道题目。 第一印象就是感觉有点像一个图的问题,感觉可以用图论的方法来解决。不过我觉得此题似乎有更简单的方法,如用动态规划(DP),可是想不出来,哪位有想法,麻烦告诉一声,呵呵。
现在我们用BFS和DFS来解决这个问题:先用BFS求出每两个o点的最短距离,然后用DFS对所有o点进行搜索,找出经过K个o点的最小步数。[code]
//001-100 01-10 10 in java language
import java.util.LinkedList;
class Point
{
public int x;
public int y;
public Point(int x,int y)
{
this.x=x;
this.y=y;
}
}
public class Doorknobs
{
public static int[][] move={{1,0},{-1,0},{0,1},{0,-1}};//在迷宫中可走的四个方向
public Point[] point; //记录迷宫中的o点
public int[][] dist; //记录任意两个o点的距离
public boolean[] used; //用于DFS时作已访问标记
public int count; //记录o点的个数
public char[][] ch; //迷宫的描述
public Doorknobs() //初始化
{
point=new Point[10];
dist=new int[10][10];
used=new boolean[10];
ch=new char[51][51];
count=0;
}
//BFS求Point(x1,y1)和Point(x2,y2)的最短距离
public int distance(String[] house,int x1,int y1,int x2,int y2)
{
int row=house.length;
int col=house[0].length();
int deep=0; //记录最短距离
for(int i=0;i {
ch[i]=house[i].toCharArray();
}
LinkedList queue=new LinkedList(); //用LinkedList实现队列
ch[x1][y1]='#'; //置访问标志
queue.add(new Point(x1,y1));
queue.add(null); //null为BFS搜索一层的标志
while(!queue.isEmpty())
{
Point p;
while((p=(Point)queue.poll())!=null)
{
int x=p.x;
int y=p.y;
if(x==x2 && y==y2) //找到
{
return deep;
}
for(int i=0;i<4;i++)
{
int nx=x+move[i][0];
int ny=y+move[i][1];
if(nx<0 || nx>=row || ny<0 || ny>=col || ch[nx][ny]=='#')
{
continue;
}
ch[nx][ny]='#'; //置访问标志
queue.add(new Point(nx,ny)); //加入队列
}
}
deep++;
queue.add(null);
}
return Integer.MAX_VALUE;
}
//从第start个点开始找left个点的最短距离
public int dfs(int start,int left)
{
int ret=Integer.MAX_VALUE;
for(int i=0;i {
if(!used[i])
{
int temp=dist[start][i];
if(left!=1)
{
used[i]=true;
temp+=dfs(i,left-1);
used[i]=false;
}
if(temp {
ret=temp;
}
}
}
return ret;
}
public int shortest(String[] house, int doorknobs)
{
int row=house.length;
int col=house[0].length();
int i=0,j=0;
for(i=0;i {
for(j=0;j {
if(house[i].charAt(j)=='o')
{
point[count]=new Point(i,j);
count++;
}
}
}
point[count]=new Point(0,0);//初始点
count++;
//dist[i][j]==dist[j][i],可以进行优化一下
for(i=0;i {
for(j=0;j {
dist[i][j]=distance(house,point[i].x,point[i].y,point[j].x,point[j].y);
//System.out.println (i+" "+j+" "+dist[i][j]);
}
}
used[count-1]=true;
int ret=dfs(count-1,doorknobs);
return (ret==Integer.MAX_VALUE)? -1 : ret;
}
public static void main(String args[])
{
Doorknobs d=new Doorknobs();
String house[]={".....","o....","o....","o....","...o."};
System.out.println (d.shortest(house,4));
}
}
[/code]再补上一个C++语言版本的:[code]
#include
#include
#include
#include
#include
using namespace std;
#define MAX 51
char house[MAX][MAX];
int m,n,k,totalKey,best;
int dis[MAX][MAX];
int x[51],y[51];
bool used[51];
struct Point
{
int x;
int y;
int len;
};
void readData(int m,int n)
{
int i,j;
x[0]=0;
y[0]=0;
totalKey++;
for(i=0; i {
scanf("%s",house[i]);
for(j=0; j {
if(house[i][j]=='o')
{
x[totalKey]=i;
y[totalKey]=j;
totalKey++;
}
}
}
}
int compute(int xa, int ya, int xb, int yb)
{
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
bool visited[MAX][MAX] = {false};
queue q;
Point p;
p.x = xa;
p.y = ya;
p.len = 0;
q.push(p);
visited[xa][ya] = true;
while(!q.empty())
{
Point top = q.front();
q.pop();
if(top.x == xb && top.y == yb)
{
return top.len;
}
for(int i=0; i<4; i++)
{
int xx = top.x+dx[i];
int yy = top.y+dy[i];
if(xx >= 0 && xx < m && yy >=0 && yy {
Point tmp;
tmp.x = xx;
tmp.y = yy;
tmp.len = top.len+1;
q.push(tmp);
visited[xx][yy] = true;
}
}
}
return -1;
}
void computedis()
{
int i,j;
for(i=0;i {
dis[i][i]=0;
for(j=i+1;j {
int d = compute(x[i],y[i],x[j],y[j]);
dis[i][j]=dis[j][i]=d;
//cout<<"dixtance "< }
}
}
//从第currentKey个开始,还需找left个,找到的长度(步数)为len
void find(int currentKey, int left, int len)
{
if(len>=best) return; //剪枝
if(left == 0)
{
if(len < best || best == -1)
{
best = len;
//cout< }
return;
}
for(int i=1; i< totalKey; i++)
{
if(i != currentKey && !used[i] && dis[currentKey][i] != -1)
{
used[i] = true;
find(i,left-1,len+dis[currentKey][i]);
used[i] = false;
}
}
}
int main()
{
int i;
//double t = clock();
while(scanf("%d%d%d",&m,&n,&k)!=EOF)
{
totalKey = 0;
readData(m,n);
computedis();
best = 100000;
for(i=0; i {
used[i] = false;
}
used[0]=true;
find(0,k,0);
if(best == 100000) best = -1;
cout< }
//cout<<(clock()-t)/CLK_TCK< }
[/code

BFS/DFS算法介绍与实现(转)的更多相关文章
- (原创)BFS广度优先算法,看完这篇就够了
BFS算法 上一篇文章讲解了DFS深度优先遍历的算法,我们说 DFS 顾名思义DEEPTH FIRET,以深度为第一标准来查找,以不撞南墙不回头的态度来发掘每一个点,这个算法思想get到了其实蛮简单. ...
- DFS 算法模板
dfs算法模板: 1.下一层是多节点的dfs遍历 def dfs(array or root, cur_layer, path, result): if cur_layer == len(array) ...
- 【2018.07.29】(深度优先搜索/回溯)学习DFS算法小记
参考网站:https://blog.csdn.net/ldx19980108/article/details/76324307 这个网站里有动态图给我们体现BFS和DFS的区别:https://www ...
- LeetCode:BFS/DFS
BFS/DFS 在树专题和回溯算法中其实已经涉及到了BFS和DFS算法,这里单独提出再进一步学习一下 BFS 广度优先遍历 Breadth-First-Search 这部分的内容也主要是学习了labu ...
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...
- 图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))
sdut 2140 图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 给定一个有向图 ...
- POJ 2227 The Wedding Juicer (优先级队列+bfs+dfs)
思路描述来自:http://hi.baidu.com/perfectcai_/item/701f2efa460cedcb0dd1c820也可以参考黑书P89的积水. 题意:Farmer John有一个 ...
- 邻结矩阵的建立和 BFS,DFS;;
邻结矩阵比较简单,, 它的BFS,DFS, 两种遍历也比较简单,一个用队列, 一个用数组即可!!!但是邻接矩阵极其浪费空间,尤其是当它是一个稀疏矩阵的时候!!!-------------------- ...
- KNN算法介绍
KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...
随机推荐
- Android issues
1. Android studio 2.0 Error:Exception in thread "main" java.lang.UnsupportedClassVersionEr ...
- Camtasia 录屏说明
准备好要录制的屏幕或网页,在即将播放的位置暂停住. 从开始菜单位置“TechSmith”启动Camtasia Recorder 8,其界面如下所示: 注意,要录制系统声音,须在Recorded inp ...
- ABAP READ TABLE语句注意
READ TABLE 后注意判断 sy-subrc 是否等于0
- java类加载器加载文件
例子:采用配置文件加反射的方式创建ArrayList和HashSet的实例对象. //第一种方式:类加载器加载文件 InputStream ips = ReflectTest2.class.getCl ...
- cocoapods真机调试出现问题解决
swift中使用cocoapods时,Podfile中必须写上 use_frameworks! 使用cocoapods导入框架在真机调试出现问题的解决方案: 1.build phases 2.+ ne ...
- MD5加密
public string Second_MD5(string str) { MD5 md5 = MD5.Create();//创建MD5实例 byte[] strbyte = Encoding.UT ...
- APM程序分析-Control_rtl.cpp
bool Copter::rtl_init(bool ignore_checks) { if (position_ok() || ignore_checks) { rtl_build_path(!fa ...
- 【纯css】响应式图片列表
示例演示 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...
- October 28th Week 44th Friday 2016
Life is not a problem to be solved, but a reality to be experienced. 人生不是待解决的难题,而是等着我们去体验的现实. Press ...
- 解决fedora25安装vmware12问题:
运行vmware需要几个工具.gcc 编译工具是必须要有的.dnf groupinstall “Development tools“rpm -qa |grep kernel-headersrpm -q ...