A long time ago, I wanted to do K short circuit. It's just a tough little dish ~.
First, let's talk about A * algorithm. As we all know, the * algorithm is A heuristic search in the basic form: f (x) = g (x) + h (x); Where f (x) represents the total cost required at x, while g (x) represents the actual cost from the source point to the x point, h (x) represents the estimated cost from x to the end. This function is an estimate. the actual cost from x to the end is h * (x). In the entire heuristic search, we must ensure that h (x) <= h * (x ); otherwise, the incorrect answer may be caused by an excessively high valuation value. The key to building A * Is to accurately plan an h (x) function so that it is close to h * (x). Such A search will make the Answer faster and more accurate. We can imagine that h (x) is too small to make the solution space too large, so that the search results will be accurate but slow, and the h (x) is too high to estimate, that is, the estimated cost is too high to make the results inaccurate.
In this way, we can understand the BFS search process. The estimated cost of h (x) is not taken into account in the BFS search process. That is to say, h (x) = 0, only g (x) is considered) the actual cost. In this way, you can search at the actual cost. Although it can be said that it is quite disgusting, we can also know that BFS has A lot of space to solve.
Write A * for the first time. Currently, it will only apply to K short circuits. But I also feel a little bit. The key lies in the design of h (x!
Specific implementation:
First, we get the smallest f (x) in the solution space, so we need to apply it to the priority queue. Here we provide a method to use the priority queue of the C ++ system:
#include<queue>struct Q{int g,h;bool operator<( Q a )const{ return a.g+a.h<g+h; }}priority_queue<Q>queue;Q b;queue.push(b);
The STL of C ++ comes with a priority queue. By using the heavy-load calculation method "<", we can achieve the automatic maintenance of f (x.
Describes how to use heuristic search to solve K short circuits.
First, we know the basic formula of A *: f (x) = g (x) + h (x); design h (x), according to the definition of h (x) the actual distance from x to t. That is to say, the distance between x-> t. Because many nodes are at the distance to t, to calculate this estimated value, we must first calculate the shortest path length of x-> t. Obviously, x has a lot of values, and t has only one value. It is not cost-effective to calculate the shortest path of a single source point for each x! Then, the shortest path of the single-Source Vertex that is sent from the t-point to the other vertex. In this case, evaluate the h (x) function and pay attention to the h (x) obtained in this way) = h * (x );
Then we can start heuristic search for the constructed h (x.
The first point is to define the head node. The cost of the head node is 0, the estimated cost is h [s], and the next point is v. Enter the queue and start the for loop. Each time the smallest node of f (x) in the team header is retrieved, other nodes are expanded. The number of expansion times for the current node is +. If the number of expansion times for the current node exceeds K, it obviously does not meet the requirements. If the number of extensions to the t node is exactly K, find the required number. The number of expansion times for the current node is the number of short circuits to the current node. Find the K short circuit of the node and return g (t), that is, the actual length consumed by K expansion.
In the for loop, all the sides of the current node can be expanded, and all the statuses are queued, the actual cost from the current node to the extended node is the actual cost of the current node + the edge length between two nodes. The next node is the expansion node, and the estimated function value is the distance from the expansion node to the target node h (x );
The solution Code is as follows:
#include<iostream>#include<cstdio>#include<queue>#define MAXN 1005#define MAXM 200100using namespace std;struct Node{ int v,c,nxt;}Edge[MAXM];int head[MAXN];int tail[MAXN];int h[MAXN];struct Statement{ int v,d,h; bool operator <( Statement a )const { return a.d+a.h<d+h; }};void addEdge( int u,int v,int c,int e ){ Edge[e<<1].v=v; Edge[e<<1].c=c; Edge[e<<1].nxt=head[u]; head[u]=e<<1; Edge[e<<1|1].v=u; Edge[e<<1|1].c=c; Edge[e<<1|1].nxt=tail[v]; tail[v]=e<<1|1; return ;}void Dijstra( int n,int s,int t ){ bool vis[MAXN]; memset( vis,0,sizeof(vis) ); memset( h,0x7F,sizeof(h) ); h[t]=0; for( int i=1;i<=n;i++ ) { int min=0x7FFF; int k=-1; for( int j=1;j<=n;j++ ) { if( vis[j]==false && min>h[j] ) min=h[j],k=j; } if( k==-1 )break; vis[k]=true; for( int temp=tail[k];temp!=-1;temp=Edge[temp].nxt ) { int v=Edge[temp].v; if( h[v]>h[k]+Edge[temp].c ) h[v]=h[k]+Edge[temp].c; } }}int Astar_Kth( int n,int s,int t,int K ){ Statement cur,nxt; //priority_queue<Q>q; priority_queue<Statement>FstQ; int cnt[MAXN]; memset( cnt,0,sizeof(cnt) ); cur.v=s; cur.d=0; cur.h=h[s]; FstQ.push(cur); while( !FstQ.empty() ) { cur=FstQ.top(); FstQ.pop(); cnt[cur.v]++; if( cnt[cur.v]>K ) continue; if( cnt[t]==K )return cur.d; for( int temp=head[cur.v];temp!=-1;temp=Edge[temp].nxt ) { int v=Edge[temp].v; nxt.d=cur.d+Edge[temp].c; nxt.v=v; nxt.h=h[v]; FstQ.push(nxt); } } return -1;}int main(){ int n,m; while( scanf( "%d %d",&n,&m )!=EOF ) { int u,v,c; memset( head,0xFF,sizeof(head) ); memset( tail,0xFF,sizeof(tail) ); for( int i=0;i<m;i++ ) { scanf( "%d %d %d",&u,&v,&c ); addEdge( u,v,c,i ); } int s,t,k; scanf( "%d %d %d",&s,&t,&k ); if( s==t ) k++; Dijstra( n,s,t ); printf( "%d\n",Astar_Kth( n,s,t,k ) ); } return 0;}
After question A is finished
1. Learned to define a linked list using arrays,
2. Use STL priority queue
3. A * preliminary understanding of Search
4. K short circuit is a solution.
:)