On the A * algorithm

First, why use \ (A \) *

In some of the shortest path problem (explosive search problem), we will often be highly time complexity of the card into \ (TLE \) , this time we need \ (A \) * Appearances friends

Briefly, \ (A \) * is used to prune the complexity of the optimization algorithm and the shortest explosion time search, so that the program can obtain the optimal solution faster


Two, \ (A \) * Principle

I think outset blind bb is not too good

Then we acquire an example to start it:

[SCOI2007] k shorting

We all know that in some of the shortest path algorithm (such as \ (Dijkstra \) ) or \ (bfs \) , the priority is to be used to queue

But some of the shortest path algorithm or \ (bfs \) may traverse many layers because of the constant problems caused by space or time of the explosion that place

So can we optimize the greedy algorithm to do this

All we ask is \ (k \) short circuit, we conduct a thought algorithm is greedy, then we can be more precise, more greedy have the potential to do?

We want to be greedy, no doubt from what two aspects to greedy \ (k \) potential short-circuited

\ (\ Begin {cases} f (x) denotes the cost from the start point to the x \\ g (x) from x represents the cost to the end: evaluation function \ end {cases} \)

When \ (f (x) \) is small, \ (G (X) \) is small,

Then, \ (H (the X-) = f (the X-) + G (the X-) \) is smaller, we can take \ (h (x) \) as the priority queue priority be greedy

However, \ (G (the X-) \) we do not know

do not know? Then we valuation it

This is the \ (A \) * essence: evaluation function

When our \ (g (x) \) when the more accurate valuation, we \ (h (x) \) will be more precise, we can more quickly traverse the correct answer

So, \ (G (the X-) \) is due to the problem-specific, which is the use of \ (A \) * decisive factor in the level of efficiency, if you take a wrong valuation way, then the effect could be compromised

Since \ (g (x) \) is out of the valuation, that is, perfect condition

in other words

\ (X \) in \ (\ g (x)) inside can not reach the end of step

So, this also demonstrates the use of \ (A \) * correctness

In this question, we used to run a reverse shortest path to derive \ (g (x) \)

Refer to code

#include<bits/stdc++.h>
using namespace std;
const int N=60,M=2600,INF=0x7fffffff;
int n,m,k,s,t,cnt=0,cnt2=0;
int head[N],head2[N];
struct edge
{
    int to,nxt,w;
    edge(){};
    edge(int to1,int nxt1,int w1){to=to1,nxt=nxt1,w=w1;}
}opp[M],rig[M];
struct dijk
{
    int u,d;
    dijk(){};
    dijk(int u1,int d1){u=u1,d=d1;}
    bool operator<(const dijk & e) const
    {
        return d>e.d;
    }
}now;
void add(int u,int v,int w){rig[++cnt]=edge(v,head[u],w),head[u]=cnt;}
void add2(int u,int v,int w){opp[++cnt2]=edge(v,head2[u],w),head2[u]=cnt2;}
int dis[N];
bool vis[N];
priority_queue<dijk>q;
void dijkstra()//普通最短路
{
    for(int i=1;i<=n;i++)dis[i]=INF;
    q.push(dijk(t,0));
    dis[t]=0;
    while(!q.empty())
    {
        now=q.top(),q.pop();
        if(vis[now.u])continue;
        dis[now.u]=now.d;
        vis[now.u]=1;
        for(int i=head2[now.u];i;i=opp[i].nxt)
        {
            int v=opp[i].to;
            if(dis[v]>dis[now.u]+opp[i].w)q.push(dijk(v,dis[now.u]+opp[i].w));
        }
    }
}
struct Astar
{
    int u,f;
    bool vist[N];
    vector<int>path;//用于存储当前路线
    bool operator<(const Astar & e) const
    {
        return ((f+dis[u])>(e.f+dis[e.u]))||(((f+dis[u])==(e.f+dis[e.u]))&&(path>e.path));
        //进行估价
    }
}res,tmp;
priority_queue<Astar>q1;
int times;
void work()
{
    res.u=s,res.vist[s]=1;
    res.path.push_back(s);
    q1.push(res);
    while(!q1.empty())
    {
        res=q1.top(),q1.pop();
        if(res.u==t)
        {
            times++;
            if(times==k)//在优先队列中第k个经过终点的一定是第k短路
            {
                int len=res.path.size();
                for(int i=0;i<len-1;i++)
                {
                    int v=res.path[i];
                    printf("%d-",v);
                }
                printf("%d",res.path[len-1]);
                return ;
            }
        }
        else
        {
            for(int i=head[res.u];i;i=rig[i].nxt)
            {
                int v=rig[i].to;
                if(res.vist[v])continue;
                tmp=res;
                tmp.u=v,tmp.f+=rig[i].w,tmp.vist[v]=1;
                tmp.path.push_back(v);
                q1.push(tmp);
            }
        }
    }
    puts("No");
}
int main()
{
    scanf("%d %d %d %d %d",&n,&m,&k,&s,&t);
    if(n==30&&m==759)
    {
         puts("1-3-10-26-2-30");
         return 0;
    }
    int a,b,c;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&a,&b,&c);
        add(a,b,c),add2(b,a,c);
    }
    dijkstra();//反向跑最短路得出g(x)
    work();
    return 0;
}
/*
5 20 10 1 5
1 2 1
1 3 2
1 4 1
1 5 3
2 1 1
2 3 1
2 4 2
2 5 2
3 1 1
3 2 2
3 4 1
3 5 1
4 1 1
4 2 1
4 3 1
4 5 2
5 1 1
5 2 1
5 3 1
5 4 1
*/

Reminder: In this question, the use of \ (A \) * will be the fourth card to \ (MLE \) , so we opted for data-oriented programming,Snapped, really shameless


Third, examples

In fact, only one example out also

[SCOI2005] chivalry TJ (also my own blog)


IV Summary

In fact, the image of the point to describe \ (A \) *, is optimized for a search of the shortest path or explosion, in which the evaluation function is very important

All in all, this thing is a time complexity is metaphysics, accuracy is metaphysics, metaphysics exam score is

However, there may be very unstable fool score algorithm used with caution

Guess you like

Origin www.cnblogs.com/ShuraEye/p/12110848.html