首先先来一题例题来解释做一个引子吧:
比如:从3开始先选择一条路来走的话,从3到2然后继续往后走到1到0,在1就不能继续往后走了,就开始回溯了。从0到1,再到2,发现2还可以走到4然后再从4走到5,再返回4返回到3,再从3到6再到5。
这个地方有提到用栈来优化深度优先搜索。这个我觉得可以想想,比如走一条路的时候不断的把结点入队,走到路的尽头的时候就把结点出队,直到某个结点还有其他相连的路为止。(这个是个人思考后面看看能不能再找一个博客来搞)。
其实之前我也有入门学过,但是当时还没有比较好的编程的思维所以就很不熟。现在重新捡起来。其实广度优先搜索就像一个广撒网的感觉。一层层的往下搜索直到找到需要找的点为止。注意在搜索的过程中要判重。肯定不能找已经走过的点。
后面是广度优先算法的基本步骤:
接下来的几张图来好好的解释一下怎么使用Open表和closed表来进行广搜的过程:
第一步;把起点入Open队列。
第二步:把3出队,通过二维数组或者是邻接表来确定与3相连的结点,把这些结点入队。
第三步:就是把队首元素给弹出来,然后把与这个元素相连的元素给压入队列尾就好了。就这样进行循环直到队列尾与头相等(也就是队列是空的时候)则无解。或者是直到弹出的元素刚好是终点的时候,那么就是找到这条路了!
后面进行代码演示:
#include <iostream> #include <cstring> #include <queue> using namespace std; int N, K; const int MAXN = 1000;//最大的结点数 int visited[MAXN + 10];//可视化数组 struct Step { //每一个Step其实是可以理解成是一种状态的 int x;//结点的编号 int steps;//相应步数 Step (int xx,int s): x(xx),steps(s){ } //函数的重载,其实可以理解成一个将Step当成一个函数用 //比如每一次将这个元素压入队列的时候用这个可以直接把相关的数搞进来 }; queue <Step> q; int main() { cin >> N >> K; memset(visited, 0, sizeof(visited)); q.push(Step(N, 0)); //这个压入的是第一个结点的信息 visited[N] = 1; //在这个之前都是广搜的起始化过程. while (!q.empty()) { //队列不为空的情况下、 Step s = q.front();//这里把队列的队列头取出 if (s.x == K) { cout << s.steps << endl; return 0; //找到了就可以控制结束程序咯 } else { //首先记得判断会不会出队 if (s.x - 1 >= 0 && !visited[s.x - 1]) { q.push(Step(s.x - 1, s.steps + 1)); visited[s.x - 1] = 1; } if (s.x + 1 <=MAXN && !visited[s.x + 1]) { q.push(Step(s.x + 1, s.steps + 1)); visited[s.x + 1] = 1; } if (s.x*2 <= MAXN && !visited[s.x*2]) { q.push(Step(s.x*2, s.steps + 1)); visited[s.x*2] = 1; } } q.pop(); } return 0; }
下篇博客来讲几篇迷宫问题吧!