[SDOI2010]魔法猪学院

K短路,A*

新鲜出炉的A
A
是什么,其实就是bfs,只不过加了一个估价函数h(x),并把队列换成了优先队列。令h(x)==已经花费的代价,f(x)=g(x)+h(x),,那么f(x)就是优先队列的比较标准。这样我们就会尽可能向最优解的方向搜索,我们如果想要求最优解,就跑A*,每次扩展状态,压入队列中,如果感觉要T了,直接结束程序,那么解极为可能就是最优解。

K短路有一个性质:估价函数是100%正确的,我们就利用优先队列扩展状态,如果我们到达了终点,就cnt++一次,直到cnt==k为止。这样我们就不会重复搜索。
但是,这种算法空间复杂度极高,IDA*正在学。

code:(92分)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#define db double
using namespace std;
const int maxn=400006;
int head[maxn],cur,fhead[maxn];
struct hzw
{
    int to,next;
    db v;
}e[maxn],ed[maxn];
inline void add(int a,int b,db c,hzw e[],int head[])
{
    e[cur].to=b;
    e[cur].next=head[a];
    e[cur].v=c;
    head[a]=cur++;
}
typedef pair <double,int>p;
int n,m;
double dis[maxn];
double k;
inline void dij(int firs)
{
    for (int i=1;i<=n;++i) dis[i]=1e17;
    priority_queue<p,vector<p>,greater<p> >q;
    q.push(p(0,firs));
    dis[firs]=0;
    while (!q.empty())
    {
        p fr=q.top();
        q.pop();
        int s=fr.second;
        if (dis[s]<fr.first) continue;
        for (int i=fhead[s];i!=-1;i=ed[i].next)
        {
            int v=ed[i].to;
            double w=ed[i].v;
            if (dis[v]>dis[s]+w)
            {
                dis[v]=dis[s]+w;
                q.push(p(dis[v],v));
            }
        }
    }
}
struct gk
{
    db l,rnd;
    int id;
    bool operator <(const gk &rhs) const
    {
        return l+rnd>rhs.l+rhs.rnd;
    }
};
inline int A_star(double lmt)
{
    priority_queue<gk>q;
    int cnt=0;
    q.push((gk){0,dis[1],1});
    while (!q.empty())
    {
        gk all=q.top();
        q.pop();
        int s=all.id;
        db leth=all.l,fina=all.rnd;
        if (s==n)
        {
            lmt-=leth;
            if (lmt<=0) return cnt;
            cnt++;
            continue;
        }
        for (int i=head[s];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            double w=e[i].v;
            q.push((gk){leth+w,dis[v],v}); 
        } 
    }
    return cnt;
}
signed main()
{
    memset(head,-1,sizeof(head));
    memset(fhead,-1,sizeof(fhead));
    cin>>n>>m>>k;
    for (int i=1,a,b;i<=m;++i)
    {
        db c;
        scanf("%d%d%lf",&a,&b,&c);
        add(a,b,c,e,head);
        add(b,a,c,ed,fhead);
    }
    dij(n);
    cout<<A_star(k);
    return 0;
}

总结:

A*算法适合解决寻找路径问题,她能尽可能的像最优解逼近。

猜你喜欢

转载自www.cnblogs.com/bullshit/p/9689763.html