BFS能够求得最短路径,因为BFS每进行一次相当于当前的路径长度。对于一个N*N矩阵,BFS最多运行n*n次。
深度优先搜索相当于一个人在走迷宫,广搜相当于是无穷人沿着不同方向走(因为每条路都同时有人走)。
DFS相当于是一个下压栈。是先进后出的原则(如果找不到,往回走,直到回到有路的地方)(DFS隐式使用了栈)
BFS使用队列,按照与起点的距离来搜索。
BFS使用一个队列来保存已经被标记但是它的邻接表还没有被访问的顶点。先把起点加入队列,然后重复以下操作直到队列为空。
1、取队列中下一个顶点V并标记它
2、把和V相邻的所有没有标记的顶点加入队列。
BFS的标记edgeto代表了它的上一个节点,它的上一个节点一定只有一种情况,代表了最短解(不一定是唯一的),因为从1,1辐射出来的点不断地在刷最短路径。
深度优先搜索优先寻找离起点最远的顶点,广度优先搜索最先找最近的顶点
深度优先找到的必然是一个连通分量(因为走到死胡同为止)
HDOJ1240
BFS最短路径
#include <iostream>
#include <queue>
#include <string>
using namespace std;
int n;
const int size =12;
int matrix[size][size][size];
int step[size][size][size];
int sx,sy,sz,dx,dy,dz;
int tx[]={1,-1,0,0,0,0};
int ty[]={0,0,1,-1,0,0};
int tz[]={0,0,0,0,-1,1};
bool check(int x,int y,int z){
if(matrix[x][y][z]==0) return false;
return true;;
}
typedef struct{
int x,y,z;
}Point;
int bfs(int x,int y,int z){
step[x][y][z]=0;
matrix[x][y][z]=0;
queue<Point> Q;
Point cur;
cur.x=x;
cur.y=y;
cur.z=z;
Q.push(cur);
while(!Q.empty()){
cur = Q.front();
Q.pop();
Point next;
if(cur.x==dx&&cur.y==dy&&cur.z==dz) return step[cur.x][cur.y][cur.z];
for(int i=0;i<6;i++){
next=cur;
next.x+=tx[i];
next.y+=ty[i];
next.z+=tz[i];
step[next.x][next.y][next.z]=step[cur.x][cur.y][cur.z]+1;
if(check(next.x,next.y,next.z)){
matrix[next.x][next.y][next.z]=0;
Q.push(next);
}
}
}
return -1;
}
int main(int argc, char const *argv[])
{
string temp;
char c;
while(cin>>temp>>n){
memset(matrix,0,sizeof(matrix));//0不能走
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
cin>>c;
if(c=='X') matrix[i][j][k]=0;
else matrix[i][j][k]=1;
}
}
}
cin>>sx>>sy>>sz>>dx>>dy>>dz;
sx++,sy++,sz++,dx++,dy++,dz++;
cin>>temp;
matrix[sx][sy][sz]=matrix[dx][dy][dz]=1;
int ans = bfs(sx,sy,sz);
if(ans>=0) cout<<n<<" "<<ans<<endl;
else cout<<"NO ROUTE"<<endl;
}
return 0;
}
从别人抄的代码有很多收获:
1.用tx,ty,tz数组模拟第三个方向的搜索,非常方便。
2.BFS是用循环而不是递归完成的,把第一个点放进去,然后就可以不断循环了,直到队列为空。
3.队列API的pop不返回弹出的元素,必须用front
附:stack和queue简单操作:
1、stack
stack 模板类的定义在头文件中。
stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要
的,在不指定容器类型时,默认的容器类型为deque。
定义stack 对象的示例代码如下:
stack s1;
stack s2;
stack 的基本操作有:
入栈,如例:s.push(x);
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()。
2、queue
queue 模板类的定义在头文件中。
与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类
型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
定义queue 对象的示例代码如下:
queue q1;
queue q2;
queue 的基本操作有:
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()