zoukankan      html  css  js  c++  java
  • 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);
        }
    }
  • 相关阅读:
    mysql 函数 存储过程 事件(event) job 模板
    protobuf 无proto 解码 decode 语言 java python
    mitmproxy fiddler 抓包 填坑
    android adb 常用命令
    android机器人 模拟 踩坑过程
    RabbitMQ添加新用户并支持远程访问
    Windows下RabbitMQ安装及配置
    Java mybatis mysql 常用数据类型对应关系
    easyExcel 踩坑
    linux防火墙查看状态firewall、iptable
  • 原文地址:https://www.cnblogs.com/sweat123/p/4890607.html
Copyright © 2011-2022 走看看