启发式搜索 luogu2483——[SDOI2010]魔法猪学院

luogu2483
这题不知道为什么,我bzoj上死都过不去
启发式搜索 luogu2483——[SDOI2010]魔法猪学院_第1张图片
然而luogu不断的调数组大小后终于卡过去了(黑人问号
内存206MB。。时间4s+
本题重点就在于求出k短路
然后很简单的贪心减一下就好了

那么接下来问题来了 k短路怎么求

Dijkstra/SPFA+A*
前一个相信大家都知道并且会写
那么注重来讲一下本题中的A*要怎么操作

首先A*的核心在于:f(x)=g(x)+h(x)
那么这里的估价函数h(x)要怎么设计呢
很显然啊。。。x->T的最短路径
所以一开始的dij或者SPFA就是用来求出T到所有节点的估价函数
g(x)为节点走到当前状态的路径长度
注意一下 并不是最短路!
原地绕两下是允许的

接下来我们只要维护一个open表
这题。。连close表都不需要
因为状态本身并不会重复:{x,g(x)}

那么先看一下A*的代码

priority_queue open;
inline void A_star()
{
    open.push((hp1){1,1,dis[1]});
    g[1]=0;
    while(!open.empty())
    {
        hp1 t=open.top();
        open.pop();
        if(t.x==n){if(e>=t.val) e-=t.val,ans++;else return;}
        for(int i=f[t.x];i;i=nxt[i])
        {

            int t1=++tot;
            int t2=poi[i];
            double t3=g[t1]=g[t.num]+v[i];
            //cout<' '<' '<open.push((hp1){t1,t2,t3+dis[t2]});
        }
    }
}

不要问我为什么是大根堆。。

 bool operator < (const hp1 &a) const
    {
        return a.val

然后加上一个dij就可以了
CODE:

#include
#include
#include
#include
#include
#define N 200000
#define For(i,j,k) for(int i=j;i<=k;++i)
using namespace std;

double z,g[500001];
int n,m,x,y,s,cnt,ans,tott;
double c1[N*2],dis[20001],e,v[N*2];
int tot,nxt1[N*2],point1[20001],v1[N*2],poi[N*2],f[20001],nxt[N*2];

bool vis[N*2];
struct hp
{
    int x;
    double val;
    bool operator < (const hp &a) const
    {
        return a.valstruct hp1
{
    int num,x;
    double val;
    bool operator < (const hp1 &a) const
    {
        return a.val500001];
priority_queue  q;

inline void addedge(int x,int y,double z)
{
    nxt1[++tot]=point1[x]; point1[x]=tot; v1[tot]=y; c1[tot]=z;
}
inline void add2(int x,int y,double z)
{
    nxt[++cnt]=f[x];f[x]=cnt;poi[cnt]=y;v[cnt]=z;
}
inline void dijkstra()
{
    For(i,1,n)  dis[i]=10000000.0;
    dis[n]=0;
    q.push((hp){n,0});
    while (!q.empty())
    {
        int now=q.top().x;
        q.pop();
        if (vis[now]) continue; 
        vis[now]=true;
        for (int i=point1[now];i;i=nxt1[i])
        {
            if (!vis[v1[i]]&&dis[now]+c1[i] open;
inline void A_star()
{
    open.push((hp1){1,1,dis[1]});
    g[1]=0;
    while(!open.empty())
    {
        hp1 t=open.top();
        open.pop();
        if(t.x==n){if(e>=t.val) e-=t.val,ans++;else return;}
        for(int i=f[t.x];i;i=nxt[i])
        {

            int t1=++tot;
            int t2=poi[i];
            double t3=g[t1]=g[t.num]+v[i];
            open.push((hp1){t1,t2,t3+dis[t2]});
        }
    }
}
int main()
{
    scanf("%d%d%lf",&n,&m,&e);
    for (int i=1;i<=m;++i)
    {
        scanf("%d%d%lf",&x,&y,&z);
        addedge(y,x,z);
        add2(x,y,z);
    }
    dijkstra();
    A_star();
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(题库)