诶,思来想去,还是要关于这个写一篇博客的。(毕竟当初为了看懂这两个东西并且自己写出代码,花了好长好长的时间。)上次蓝桥杯中出现了一道关于迷宫的题目,当时写了好久写不出来,很气,于是下定决心要把这两个东西看看懂。而最近又回到了图论的问题,于是这两玩意又出来了。。
第一次接触DFS,是在《啊哈,C》中 解救小哈 一问题的解决。
先来讲一下这两者的算法思想吧。(这里感谢我大oy)
广度优先搜索(BFS),也称为宽度优先搜索。其思想在图上画出来就像一个石子被丢进池塘中,激起的波纹。在图中,他从起点开始,记录下能够走到的位置,然后走到下一个点,同时把上一个点给标记掉(即不要往回走),然后下一个点,继续上面的操作。直到第一次出现重点,就可以结束了(若是找最短路径)。
深度优先搜索(DFS),俗称“不撞南墙不回头”,就从一条路开始,下一个点,下一个点,直至走到不能走到的点,然后回溯同时标记死胡同,走到能有下一条路的路口,向下一个没有标记的点走。
从算法思想来看,广度优先搜索适合找最短路径(要是题目要求输出最短路径长度,那就最简单了),而加上对上一点的记录,也就可以还原原来的路径。深度优先搜索个人认为更加适合有优先方向的题目,同时也可以还原路径。
而后,又在oj上写到这么一道题:
迷宫是一个二维矩阵,其中1为墙,0为路,3为入口,4为出口.要求从入口开始,从出口结束,按照 下,左,上,右 的顺序来搜索路径.
迷宫宽度w 迷宫高度h
迷宫第一行
迷宫第二行
…
迷宫第h 行
入口横坐标1 入口纵坐标1
横坐标2 纵坐标2
横坐标3 纵坐标3
横坐标4 纵坐标4
…
横坐标n-1 纵坐标n-1
出口横坐标n 出口纵坐标n
8 10
1 1 1 1 1 1 1 1
1 0 1 1 0 1 0 1
1 0 1 0 0 1 0 1
1 1 0 3 1 0 1 1
1 0 0 1 0 0 4 1
1 0 0 0 0 1 1 1
1 0 1 0 0 1 0 1
1 0 1 0 0 0 1 1
1 1 1 1 0 0 0 1
1 1 1 1 1 1 1 1
3 3
2 3
2 4
2 5
3 5
3 6
3 7
4 7
4 6
4 5
4 4
5 4
6 4
这是最直接明了的迷宫问题了,找出路径,并输出路径就行了,且这里使用优先队列思想。
这题当时使用c语言写的一段DFS的代码。(这里没有用上stl库的队列,还自己写了一个)
#include
#include
#include
#include
#include
#include
#define len 999
using namespace std;
typedef struct node
{
int x;
int y;
int f;
} position;
int Next[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};
int row,line,start_x,start_y,end_x,end_y,flag = 0,lon = 0;
int maze[len][len], book_maze[len][len];
position que[len][len];
position book_que[len*len];
void Search_the_position(int p,int &x,int &y);
void dfs(int x,int y);
void way_print();
int main()
{
cin>>line>>row;
for (int i=0; i=row||now_y<0||now_y>=line)
continue;
if (book_maze[now_x][now_y]==0 && maze[now_x][now_y]==0)
{
book_maze[now_x][now_y] = 1;
que[now_x][now_y].x = x;
que[now_x][now_y].y = y;
dfs(now_x,now_y);
}
}
}
void way_print()
{
int mx = end_x,my = end_y;
int nx,ny;
int i = 0;
nx = que[mx][my].x;
ny = que[mx][my].y;
while (mx!=start_x||my!=start_y)
{
book_que[i].x = mx;
book_que[i].y = my;
mx = nx;
my = ny;
nx = que[mx][my].x;
ny = que[mx][my].y;
i++;
}
cout<
代码不难。
之后又是另一道题:
设计一个算法找一条从迷宫入口到出口的最短路径。
迷宫的行和列m n
迷宫的布局
最短路径
6 8
0 1 1 1 0 1 1 1
1 0 1 0 1 0 1 0
0 1 0 0 1 1 1 1
0 1 1 1 0 0 1 1
1 0 0 1 1 0 0 0
0 1 1 0 0 1 1 0
(6,8)(5,7)(4,6) (4,5)(3,4) (3,3) (2,2)(1,1)
这题 可以用来练习BFS,代码如下(这题是用c写的,而且不知道为什么当时都放在main函数里面去了,下次一定要注意- -。)
#include
#include
typedef struct note
{
int x;
int y;
int f;
int s;
} seat;
int next[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}};
void Init_que(seat*, int, int,int );
void Print(int ,seat*);
int main()
{
int w,h;
scanf("%d%d", &h, &w);
seat que[w*h+1];
int labyrinth [w][h] ;
int book_labyrinth [w][h] ;
int head,tail;
int i,j,k,startx,starty,tx,ty,flag;
int endx,endy;
for (j=0; jw-1||ty<0||ty>h-1)
continue;
if (labyrinth[tx][ty]==0 && book_labyrinth[tx][ty]==0)
{
book_labyrinth[tx][ty] = 1;
que[tail].x = tx;
que[tail].y = ty;
que[tail].f = head;
que[tail].s = que[head].s + 1;
tail++;
}
if (tx==endx && ty==endy)
{
flag = 1;
break;
}
}
if (flag == 1)
break;
head++;
}
Print(tail, que);
return 0;
}
void Init_que(seat *que, int tail, int startx, int starty)
{
que[tail].x = startx;
que[tail].y = starty;
que[tail].f = 0;
que[tail].s = 0;
}
void Print(int tail, seat *que)
{
int goback = que[tail-1].f;
printf("(%d,%d)\n", que[tail-1].y+1, que[tail-1].x+1);
while(goback!=0)
{
printf("(%d,%d)\n", que[goback].y+1, que[goback].x+1);
goback = que[goback].f;
}
代码也不难,用队列实现而不是用递归(在班主任敲击下,改)。
而这里的所有代码还只是针对迷宫,还没有体现其他的图的遍历,而那之后的算法与代码,将会在之后的博客中得以体现。