• poj2449第K短路问题(A*算法)


    启发函数:f(x)=g(x)+h(x);

    g(x)表示初始点到x状态的代价,h(x)表示从x的状态到目标状态的代价的估计值(并不是真实的),实际最小代价<=h(x);

    起点s,终点t,x.v=s,x.len=0;然后优先队列中f(x)值最小值出队列,再根据出队列的x.v状态发展下一层。如果出队列时第一次遇到x.v==t,

    就找到了s到t的最短路。...如果第k次,那就是第k短。为了加速计算,h(p)需要在A*搜索之前进行预处理,只要将原图的所有边反向,

    再从终点t做一次单源点最短路径就能得到每个点的h(p)了;

    其实到现在可以发现,如果g(x)为0,那么求出来的就是最短路系列,如果h(x)为0,求出来的就是BFS最少次数。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #define INF 99999999
    using namespace std;
    const int maxn = 1100;
    struct Enode
    {
        int to;
        int val;
        int next;
    }edge1[100100],edge2[100100];
    struct node
    {
        int to;
        int g,f;//g别的点到此状态的代价 f启发函数
        friend bool operator<(node a,node b){
            if(a.f!=b.f)
                return a.f>b.f;
            return a.g>a.g;
        }
    };
    int n,dis[maxn],pre1[maxn],pre2[maxn],index1,index2;
    void init()
    {
        index1=index2=1;
        memset(pre1,-1,sizeof(pre1));
        memset(pre2,-1,sizeof(pre2));
    }
    void add1(int x,int y,int z)
    {
        edge1[index1].to=y;
        edge1[index1].val=z;
        edge1[index1].next=pre1[x];
        pre1[x]=index1++;
    }
    void add2(int x,int y,int z)
    {
        edge2[index2].to=y;
        edge2[index2].val=z;
        edge2[index2].next=pre2[x];
        pre2[x]=index2++;
    }
    void spfa(int s)
    {
        queue<int>q;
        int vis[maxn],i,j;
        for(i=0;i<=n;i++)
        {
            vis[i]=0;
            dis[i]=INF;
        }
        dis[s]=0;
        vis[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            vis[t]--;
            if(vis[t]>n)
                break;
            for(i=pre2[t];i!=-1;i=edge2[i].next)
            {
                if(dis[edge2[i].to]>dis[t]+edge2[i].val)
                {
                    dis[edge2[i].to]=dis[t]+edge2[i].val;
                    q.push(edge2[i].to);
                }
            }
        }
    }
    int A_star(int s,int t,int k)
    {
        node temp;
        priority_queue<node>q;
        int cnt=0;
        if(s==t) k++;
        if(dis[s]==INF)
            return -1;
        temp.to=s;
        temp.g=0;
        temp.f=temp.g+dis[temp.to];
        q.push(temp);
        while(!q.empty())
        {
            temp=q.top();
            q.pop();
            if(temp.to==t)
            {
                cnt++;
            }
            if(cnt==k)
            {
                return temp.g;
            }
            for(int i=pre1[temp.to];i!=-1;i=edge1[i].next)
            {
                node tt;
                tt.to=edge1[i].to;
                tt.g=temp.g+edge1[i].val;
                tt.f=tt.g+dis[tt.to];
                q.push(tt);
            }
        }
        return -1;
    }
    int main()
    {
        int i,j,m;
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(i=0;i<m;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add1(x,y,z);//原图
                add2(y,x,z);//反向图
            }
            int s,t,k;
            scanf("%d%d%d",&s,&t,&k);
            spfa(t);
            int ans=A_star(s,t,k);
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    Nginx编译安装
    Docker下mysql容器开启binlog日志(保留7天)
    podman
    error: audit:backlog limit exceeded
    64位win2003/win2008系统IIS6.0/7.5配置PHP的方法
    iis7.5安装配置php环境详细清晰教程,三步实现【图文】
    Windows下IIS+PHP 5.2的安装与配置
    无线路由MAC地址过滤安全可靠性讨论
    debian flam3 源码
    debian flam3 依赖文件
  • 原文地址:https://www.cnblogs.com/sweat123/p/4890607.html
Copyright © 2020-2023  润新知