Hours I "A * algorithm basic strategy
--a* (A Star) is just the upgrade of BFS, when BFS all time out ...
Also in the queue-based structure, BFS uses a FIFO queue (A * queue), while a * uses a priority queueing (priority_queue). Very similar to the BFS optimization, but the general BFS optimization is just equivalent to using an optimal pruning , occasionally does not have enough optimization so the tle.
So a * algorithm improves its prioritization method by using an heuristic function (yes, the name of the water), which can "optimistically" estimate the cost of reaching the target State from the current state, and the pre-estimate must be less than or equal to the actual value , otherwise a * The algorithm will go wrong.
General Search Questions
This is a * solution scope and other search algorithms can be implemented by the scope of the problem overlap field
Timeless Classic eight-digit question
• The following references are from POJ 1077The 15-puzzle have been around for over years; Even if you don't know it by so name, you ' ve seen it. It is constructed with the sliding tiles, each with a number from 1 to the IT, and all packed into a 4 by 4 frame with on E tile missing. Let's call the missing tile ' x '; The object of the puzzle is to arrange, the tiles so, they are ordered as:
1 2 3
5 6 7
13 14 15
Where the only legal operation are to Exchange ' X ' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7
9 x 9 x 9 10 11 12
Each of the 13 14 15 X
R-> d->
The letters in the previous row indicate which neighbor of the ' x ' tile are swapped with the ' X ' tiles at each step; Legal values is ' r ', ' l ', ' u ' and ' d ', for-right, left-up, and-down, respectively.
Not all puzzles can solved; In 1870, a man named Sam Loyd is famous for distributing an unsolvable version of the puzzle, and frustrating many people . In fact, any of the regular puzzle into a unsolvable one are to swap the tiles (not counting the missing ' X ' tile, of course).
In this problem, you'll write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement.
• parsing
This problem is obviously a search problem, but a little deformed ... It's a lot harder. Of course, this problem with BFS or two-way BFS can be, but a * algorithm actual running time is better.
1. Heuristic function
As the essence of the whole * algorithm, this function is very important, then the following gives 2 ideas:
Train of Thought A:h ()-How many elements in the current state are not in the correct position; G ()-The depth of the current search, which is the number of operands used; The last operation will return 2 elements in a single operation, so the Heuristic function f () =h () -1+g ();
Evaluation: This heuristic function must be correct, but usually with the real value is too large, not particularly excellent;
Idea B:h ()-The sum of the distance between the right position and the correct position of the Manhattan element (without the vacancy) in the current state; G ()-The depth of the current search, which is the number of operands used; Since the return of an element to the bit requires at least H () operation;
Evaluation: The estimated value is close to the real value and does not exceed the real value;
2. Definition of priority queue
The priority queue is the data structure on which a * algorithm relies. STL's priority_queue
ability to automate sequencing, but with one drawback-when an output path is required, the STL queue does not provide a function to access the deleted element, so the path cannot be output by recording the "Father" state, which requires a handwritten priority queue ... QwQ
For the time being, this embarrassing situation is not considered, but it is only the shortest possible operation times. Then we need a structure:
struct Node{ int pri,code,whe,dep; //优先级H(),八数码数字表示,空位的位置,搜索深度}booloperator <(Node A,Node B) {return A.pri+A.dep>B.pri+B.dep;}
This defines the priority after which you can use the STL to sort directly ~
3. If the code does not understand can read this blog:
Eight Eight Digital issues
· Source
For reference only, if there is a shortage (I know it is a bit complicated) please comment that
/*lucky_glass*/#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define MOD 1000003struct Node {int pri,code,whe,dep;} Push;bool operator < (Node A,node B) {return A.PRI+A.DEP>B.PRI+B.DEP;} int Num[10];int Move[4]={-3,-1,3,1};long Long ten_n[]={ 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000};vector<int> Vis[MOD];inline int H (int n) {int res=0; for (int i=9;i>0;i--, n/=10) {int v=n%10==0? 9:n%10; int x1= (i-1)/3+1,y1=i%3==0? 3:i%3; int x2= (V-1)/3+1,y2=v%3==0? 3:v%3; Res+=abs (x1-x2) +abs (y1-y2); } return res; Inline long long change (int n,int a,int b) {long long a=n%ten_n[9-a+1]/ten_n[9-a],b=n%ten_n[9-b+1]/ten_n[9-b],ret; Ret=n-a*ten_n[9-a]-b*ten_n[9-b]; Ret=ret+b*ten_n[9-a]+a*ten_n[9-b]; return Ret;} inline bool Find (int n) {int m=n%mod; for (int i=0;i<vis[m].size (); i++) if (vis[m][i]==n) return true; Vis[m].push_back (n); return false;} int main () {//Freopen ("In.txt", "R", stdin); Priority_queue<node> que; for (int i=0,j=0;i<9;i++) {scanf ("%d", &num[j]); PUSH.CODE=PUSH.CODE*10+NUM[J]; if (Num[j]) j + +; else push.whe=i+1; } int end=0; for (int i=0,x;i<9;i++) scanf ("%d", &x), end=10*end+x; Push.pri=h (Push.code); Que.push (push); while (!que.empty ()) {Node top=que.top (); Que.pop (); for (int i=0;i<4;i++) {push=top; Push.whe+=move[i]; push.dep++; if (push.whe<=0 | | push.whe>9 | | (i%2 && (push.whe-1)/3!= (top.whe-1)/3)) Continue push.code= (int) change (push.code,push.whe,top.whe); if (Find (Push.code)) continue; if (push.code==end) {printf ("%d", PUSH.DEP); return 0; } push.pri=h (Push.code); Que.push (push); }} puts ("-1"); return 0;}
The real problem is the digital problem
BFs really can't live ...
UVA 15-puzzle problem
· Analytical
The only difference between the two problems is the size of the data, 8 digital may not be more than 9! species, but 15 of the digital may be in 16! So only with the general weight does not play any good role, so the use of a * algorithm, the heuristic function and the original. But......
No one is perfect, a * algorithm is flawed QwQ
Just as the bidirectional bfs,a* algorithm is faster in general, and this is generally the case with solutions. If there is no solution, the bidirectional search will degenerate into two disjoint circles, wasting space and wasting time, whereas a * algorithm will degenerate into a normal BFS (which requires searching all the solutions) and is slower than the normal BFS-the time complexity of each insertion is O (log siz). 15 There is still no solution to the digital, so in order to avoid time-out (all cases will definitely time out), we need to pre-award:
bool If_ans(int brd[][4]){ int sum=0,siz=0,x,y,tmp[17]={}; for(int i=0;i<4;i++) for(int j=0;j<4;j++) { tmp[siz++]=brd[i][j]; if(!brd[i][j]) x=i,y=j; } for(int i=0;i<16;i++) for(int j=i+1;j<16;j++) if(tmp[j]<tmp[i] && tmp[j]) sum++; if((sum+x)%2==0) return false; return true;}
The above code means--4*4 15 digital matrix after 0, each line to form a chain table (TMP), to find out the number of reverse pairs (sum), if the number of rows with 0 (the number of rows from 0) and is a multiple of two, there is no solution, otherwise there is a solution. This is actually the following:
The most authoritative proof of English:Workshop java-solvability of the Tiles Game
· Source
This code is not very good, in fact, the use of UVA data vulnerability, the real solution is ida*, and then again
/*lucky_glass*/#include <cstdio>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <iostream>using namespaceStdConst intmov[4][2]={{0,1},{0,-1},{1,0},{-1,0}};Const intfin[ -][2]={{3,3},{0,0},{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{1,3},{2,0},{2,1},{2,2},{2,3},{3,0},{3,1},{3,2},{3,3}};Const Charchr[]="Rldu";structstate{intpri,dep,x,y,brd[4][4]; String ans;BOOL operator< (ConstState &cmp)Const{returnpri+dep>cmp.pri+cmp.dep;}};inline intDis (intXintYintFxintFY) {returnABS (X-FX) +abs (y-fy);}intGet_pri (intbrd[][4]){intsum=0; for(intI=0;i<4; i++) for(intj=0;j<4; j + +) {if(!brd[i][j] | | (i==fin[brd[i][j]][0] && j==fin[brd[i][j]][1]))Continue; Sum+=dis (i,j,fin[brd[i][j]][0],fin[brd[i][j]][1]); }return 4*sum;}BOOLIf_ans (intbrd[][4]){intsum=0, siz=0, x,y,tmp[ -]={}; for(intI=0;i<4; i++) for(intj=0;j<4; j + +) {Tmp[siz++]=brd[i][j];if(!brd[i][j]) x=i,y=j; } for(intI=0;i< -; i++) for(intJ=i+1;j< -; j + +)if(Tmp[j]<tmp[i] && tmp[j]) sum++;if((sum+x)%2==0)return false;return true;}BOOLA_star (State srt) {priority_queue<state> que; State Top,pus; Que.push (SRT); while(!que.empty ()) {top=que.top (); Que.pop (); for(intI=0;i<4; i++) {pus=top; pus.x+=mov[i][0]; pus.y+=mov[i][1];if(pus.x<0|| Pus.x>3|| pus.y<0|| Pus.y>3)Continue; Swap (pus.brd[pus.x][pus.y],pus.brd[top.x][top.y]); pus.dep++;if(pus.dep> -)Continue; Pus.ans+=chr[i]; Pus.pri=get_pri (PUS.BRD);if(! PUS.PRI) {cout<<pus.ans<<endl;return true;}if(Pus.ans.size () >=2) {intF1=pus.ans.size ()-1, F2=pus.ans.size ()-2;if((pus.ans[f1]==' U '&& pus.ans[f2]==' D ') || (pus.ans[f1]==' D '&& pus.ans[f2]==' U ') || (pus.ans[f1]==' L '&& pus.ans[f2]==' R ') || (pus.ans[f1]==' R '&& pus.ans[f2]==' L '))Continue; } que.push (Pus); } }return false;}intMain () {intT;SCANF ("%d", &t); while(t--) {State SRT; for(intI=0;i<4; i++) for(intj=0;j<4; j + +) {scanf ("%d", &srt.brd[i][j]);if(!srt.brd[i][j]) srt.x=i,srt.y=j; }if(! If_ans (SRT.BRD)) {printf ("This puzzle was not solvable.\ n");Continue; } srt.dep=0; srt.pri=0;if(! A_star (SRT)) printf ("This puzzle was not solvable.\ n"); }return 0;}
K-Short-circuit problem
The rest of the search is out of the question (' @@facesymbol@@′)
A problem k-th shortest
POJ 2449
(the title is in the hyperlink)
· Analytical
In fact, the standard K short circuit. If a general search is sure to be tle, then why A * can be done? The reasons are as follows:
- A * algorithm utilizes a priority queue, so the K-path it finds in order must be a short path of k;
- It has a maximum time complexity of only more than BFS O (\log siz), so the time complexity is not high;
- We can find only one BFS by the shortest path of k-times;
Unlike the previous algorithm, we will have a penalty in the original * algorithm, and discard the priority low, but because the K short circuit, the same path may go multiple times to reach the short path of K. such as the following:
But this also causes some trouble, sometimes without solution:
And then back to the A * algorithm-because we sort by priority, our current team head element must be the best case of the entire queue now (assuming that the heuristic function is written right), so when we first n search to the end, the current path is the nth short path, in order to avoid accidents, We can also first push the situation to the end of the queue, when the entire operation is finished again to reach the end of the case as the team head, it is indeed the nth short.
According to this nature, we can when the team head element is the end point, the record is the first time to access to the end point, if it happens to be nth time, then return the answer-note: at this point, although access to the end, but also to push the situation into the queue, otherwise see the counter example .
Don't hurry to write code, there is a small hole. As we are judging whether the team head is the end, so when the starting point coincident, press test instructions should not be the shortest path, but when the program entered the BFS will be recorded once. So we give a special sentence-when the starting point is coincident, k++.
• Source code
/*lucky_glass*/#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <vector>using namespaceStd#define POIstructline{intV,len;};structstate{intU,dep,pri;BOOL operator< (ConstState CMP)Const{if(CMP.PRI==PRI)returncmp.dep<dep;Else returncmp.pri<pri; }};vector<line> Lec[poi+5],dis_lec[poi+5];intN_poi,n_edg,srt,fin,kth,inf;intDis[poi+5];inlineLine Make_line (intVintL) {returnLine{v,l};};voidSPFA () {BOOLVis[poi+5]={}; memset (DIS,0x3f,sizeofdis); inf=dis[0]; queue<int> que; dis[fin]=0; Que.push (Fin); while(!que.empty ()) {intFro=que.front (); Que.pop (); vis[fro]=false; for(intI=0; I<dis_lec[fro].size (); i++) {intPUS=DIS_LEC[FRO][I].V;if(Dis[pus]>dis[fro]+dis_lec[fro][i].len) {Dis[pus]=dis[fro]+dis_lec[fro][i].len;if(!vis[pus]) Que.push (Pus), vis[pus]=true; } } }}intA_star () {if(Srt==fin) kth++;if(Dis[srt]==inf)return -1; Priority_queue<state> que; Que.push (STATE{SRT,0, DIS[SRT]});inttot=0; while(!que.empty ()) {State top=que.top (); Que.pop ();if(Top.u==fin) {tot++;if(tot==kth)returnTOP.DEP; } for(intI=0; I<lec[top.u].size (); i++) {State pus=top; Pus.dep+=lec[top.u][i].len; PUS.U=LEC[TOP.U][I].V; PUS.PRI=DIS[PUS.U]+PUS.DEP; Que.push (Pus); } }return -1;}intMain () {scanf ("%d%d", &N_POI,&N_EDG); for(intI=0, u,v,l;i<n_edg;i++) scanf ("%d%d%d", &u,&v,&l), Lec[u].push_back (Line{v,l}), Dis_lec[v].push_back (line{u,l}); scanf"%d%d%d", &srt,&fin,&kth); SPFA (); printf"%d\n", A_star ());return 0;}
The Endthanks for reading!
-lucky_glass
"Hours summary" school hours · A * algorithm