BFS, bidirectional BFs and a*table of Contents
- 1. BFS
- 2. Two-way BFS
- 3. A * algorithm
It is useless to say or not to practise. We start with the well-known POJ 2243 topic: Given a starting point and an end point. The minimum number of moves from the starting point to the end point, according to the Knight's Walk (the word of the day)
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd2rraxjjaghvzmy=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/center ">
Set A to the start of the pathfinding and B as the destination end point.
1BFS
BFS is in fact a degenerate * algorithm. As he has no revelation function to guide
Simple code such as the following:
#include <iostream> #include <queue>using namespace Std;char ss[3];char ee[3];typedef struct node{int x; int y; int steps;} Node;int d[8][2]={{-2,1},{-2,-1},{-1,-2},{-1,2},{2,-1},{2,1},{1,-2},{1,2}};int Visited[8][8];node S;node e;int in ( Node N) {if (n.x<0| | n.y<0| | n.x>7| | N.Y>7) return 0; return 1;} void BFs () {queue<node>q; memset (visited,0,sizeof (visited)); Q.push (s); Visited[s.x][s.y]=1; while (!q.empty ()) {node St=q.front (); Q.pop (); if (st.x==e.x&&st.y==e.y) {printf ("To get from%s to%s takes%d Knight moves.\n", Ss,ee,st.steps ); Break } for (int i=0;i<8;++i) {node T; T.X=ST.X+D[I][0]; T.Y=ST.Y+D[I][1]; if (in (t) &&visited[t.x][t.y]==0) {visited[t.x][t.y]=1; t.steps=st.steps+1; Q.push (t); }}}}int main (int argC, Char *argv[]) {while (scanf ("%s%s", Ss,ee) ==2) {s.x=ss[0]-' a '; s.y=ss[1]-' 1 '; e.x=ee[0]-' a '; e.y=ee[1]-' 1 '; BFS (); } return 0;}
2Two-way BFS
A two-way BFS is a two queue. A queue is saved from the beginning of the start of the state, there is a state to save from the end of the forward search, the two-way BFS is mainly to distinguish between each grid from the beginning of the search or from the end of the search. The number of steps that each pass through the lattice node is saved to the grid. So if both sides intersect, the sum is the result.
Obvious time-saving
#include <iostream> #include <queue>using namespace Std;char ss[3];char ee[3];typedef struct node{int x; int y; int steps;} Node;int D[8][2]={{-2,1},{-2,-1},{-1,-2},{-1,2},{2,-1},{2,1},{1,-2},{1,2}};int Visited[8][8];int color[8][8];// Distinguishes the current position from which queue was searched for node S;node e;int in (node N) {if (n.x<0| | n.y<0| | n.x>7| | N.Y>7) return 0; return 1;} int BFs () {queue<node>qf; I found that if I put the QF and QB outside. The time saved is amazing and takes 16MS queue<node>qb; memset (visited,0,sizeof (visited)); memset (color,0,sizeof (color)); Qf.push (s); Qb.push (e); visited[s.x][s.y]=0; Visited[e.x][e.y]=1; color[s.x][s.y]=1;//coloring color[e.x][e.y]=2; while (!qf.empty () | |! Qb.empty ()) {if (!qf.empty ()) {node St=qf.front (); Qf.pop (); for (int i=0;i<8;++i) {node T; T.X=ST.X+D[I][0]; T.Y=ST.Y+D[I][1]; if (in (t)) { if (color[t.x][t.y]==0) {visited[t.x][t.y]=visited[st.x][st.y]+1; Color[t.x][t.y]=1; Qf.push (t); } else if (color[t.x][t.y]==2) {return VISITED[ST.X][ST.Y]+VISITED[T.X][T.Y]; }}}} if (!qb.empty ()) {node St=qb.front (); Qb.pop (); for (int i=0;i<8;++i) {node T; T.X=ST.X+D[I][0]; T.Y=ST.Y+D[I][1]; if (in (t)) {if (color[t.x][t.y]==0) {visited[t.x][t.y]=visited[st. x][st.y]+1; color[t.x][t.y]=2; Qb.push (t); } else if (color[t.x][t.y]==1) {return VISITED[ST.X][ST.Y]+VISITED[T.X][T.Y]; } } }}}}int Main (int argc, char *argv[]) {//Freopen ("In.txt", "R", stdin); while (scanf ("%s%s", Ss,ee) ==2) {s.x=ss[0]-' a '; s.y=ss[1]-' 1 '; e.x=ee[0]-' a '; e.y=ee[1]-' 1 '; s.steps=0; E.steps=1; if (s.x==e.x&&s.y==e.y) printf ("To get from%s to%s takes 0 Knight moves.\n", Ss,ee); else printf ("To get from%s to%s takes%d Knight moves.\n", Ss,ee,bfs ()); } return 0;}
3A * algorithm
The key to choosing which squares to pass through in the path is the following equation: F = G + H here:
- G = from beginning A. Along the resulting path, move to the grid to specify the movement cost of the squares.
- H = Estimated movement cost of moving from that square on the grid to end B.
This is often called a revelation, and may confuse you.
The reason for this is because it's just a push. We have no way of knowing the length of the path beforehand, because there may be various obstacles (wall, water). And so on).
The * algorithm steps are:
- Add the start grid to the open list.
- Repeat for example the following work:
- Look for the grid with the lowest F value in the Open list. We call it the current lattice.
- Switch it to the close list.
- To each of the adjacent lattices?
- Stop it. When you
- Save the path. Start with the target and move along the parent node of each cell until you return to the start grid.
This is your path.
To be able to say this, BFS is a special case of a * algorithm.
For a BFS algorithm, each node that is extended from the current node (assuming no access has been asked) is put into the queue for further expansion. In other words, the expected function H of BFS is always equal to 0. There is no hint of information. Can feel that BFS is the "worst" a * algorithm.
Select the minimum estimate: If you have learned the data structure. You should be able to know the node that selects the minimum value for each time. The minimum priority queue (also called the Least-squares heap) should be used. In C + + STL There is a ready-made data structure priorityqueue. can be used directly. Of course, don't forget to reload the comparison operator that defines the node.
Just above optimized two-way BFS (16MS)
#include <iostream> #include <queue> #include <stdlib.h>using namespace Std;char Ss[3];char ee[3]; typedef struct node{int x; int y; int steps; int g; int h; int F; friend BOOL operator < (const node & a,const node &b);} node;inline BOOL operator < (const node & a,const node &b) {return a.f>b.f;} int D[8][2]={{-2,1},{-2,-1},{-1,-2},{-1,2},{2,-1},{2,1},{1,-2},{1,2}};int Visited[8][8];node S;node e;int in (node N) {if (n.x<0| | n.y<0| | n.x>7| | N.Y>7) return 0; return 1;} int heuristic (const node &a) {return (ABS (a.x-e.x) +abs (a.y-e.y)) *10;} Manhattan (Manhattan) valuation function priority_queue<node> q; Minimum priority queue (open list) There's a bit of an optimization strategy here, because I found the hypothesis to put Q//in the Astar function. The code runs up to 157MS, and the outside word is 47MS. There are notable differences in the int Astar () {while (!q.empty ()) Q.pop (); memset (visited,0,sizeof (visited)); Q.push (s); while (!q.empty ()) {node front=q.top (); Node T; Q.pOP (); Visited[front.x][front.y]=1; if (front.x==e.x && front.y==e.y) return front.steps; for (int i=0;i<8;i++) {t.x=front.x+d[i][0]; T.Y=FRONT.Y+D[I][1]; if (in (t) && visited[t.x][t.y]==0) {t.g=23+front.g; T.h=heuristic (t); T.f=t.g+t.h; t.steps=front.steps+1; Q.push (t); }}}}int Main (int argc, char *argv[]) {//freopen ("In.txt", "R", stdin); while (scanf ("%s%s", Ss,ee) ==2) {s.x=ss[0]-' a '; s.y=ss[1]-' 1 '; e.x=ee[0]-' a '; e.y=ee[1]-' 1 '; s.steps=0; s.g=0; S.h=heuristic (s); S.f=s.g+s.h; if (s.x==e.x&&s.y==e.y) printf ("To get from%s to%s takes 0 Knight moves.\n", Ss,ee); else printf ("To get from%s to%s takes%d Knight moves.\n", Ss,ee,astar ()); } return 0;}
This article extracts the main implementation of BFS and two-way BFS and the basic principle of a *. Because the principle is not very difficult to understand and graphical process, so can master the principle of one-time (although the introduction of the text is quite brief, just as if there is nothing to say). The remaining hands-on problem.
If you have any suggestions or criticisms and additions, please leave a message stating that it is appreciated that many other references please visit the Internet.
Author:kirchhoff
Created:2014-11-14 Fri 17:43
Emacs 24.4.1 (ORG mode 8.2.10)
Uri=referer ">validate
Copyright notice: This article Bo Master original articles, blogs, without consent may not be reproduced.
BFS, two-way BFS and A *