A*是bfs的优化,IDA*是dfs的优化

A*算法: 为启发式算法中很重要的一种,被广泛应用在最优路径求解和一些策略设计的问题中。而A*算法最为核心的部分,就在于它的一个估值函数的设计上:

f(n)=g(n)+h(n) 其中f(n)是每个可能试探点的估值,它有两部分组成:一部分为g(n),它表示从起始搜索点到当前点的代价(通常用某结点在搜索树中的深度来表示)。另一部分,即h(n),它表示启发式搜索中最为重要的一部分,即当前结点到目标结点的估值,h(n)设计的好坏,直接影响着具有此种启发式函数的启发式算法的是否能称为A*算法。


题目(代码和原题稍微不同):

链接:POJ2449

第一行为n个点,m条边,求第k短路。

接下来m行,每行3个数,代表起点、终点、边权。

输出第k短路的路径长度。

解法:

K短路的定义:假设从1出发,有M条长度不同的路径可以到达点N,则K短路就是这M条路径中第K小的路径长度。 以上所述,设f[n]为最终所求,则f(n)=g(n)+h(n);h(n)就是我们所说的‘启发式函数’,表示为重点t到其余一点p的路径长度,g(n)表示g当前从s到p所走的路径的长度。

即:估价函数=当前值+当前位置到终点的距离

Solution:

(1)将有向图的所有边反向,以原终点t为源点,求解t到所有点的最短距离;

(2)新建一个优先队列,将源点s加入到队列中;

(3)从优先级队列中弹出f(p)最小的点p,如果点p就是t,则计算t出队的次数;

如果当前为t的第k次出队,则当前路径的长度就是s到t的第k短路的长度,算法结束;

否则遍历与p相连的所有的边,将扩展出的到p的邻接点信息加入到优先级队列;

代码如下:

#include<cstdio>
#include<vector>
#include<queue>
using namespace std; const int inf = 999999999;
const int maxn = 500000 + 5;
int n, m, k, s, t; struct edge {
int v, w;
};
vector<vector<edge>>a, b;
vector<int>dis(maxn, inf);
vector<bool>flag(maxn, false); //f(n)=g(n)+h(n)
//估价函数=当前值+当前位置到终点的距离
struct node {
int id;///当前节点编号
int f;//f表示经过当前节点的最短路
int g;//g表示S->当前节点的最短路
node(int id = 0, int f = 0, int g = 0) :id(id), f(f), g(g) {}
bool operator <(const node &a)const {//估价函数值大或者距初始点最长的结点优先级高
if (f == a.f) return g>a.g;
return f>a.f;
}
}; void add_edge(int u, int v, int w) {
edge tmp;
tmp.v = u; tmp.w = w; a[v].push_back(tmp);
tmp.v = v; tmp.w = w; b[u].push_back(tmp);
} void spfa(int s) {
queue<int>q;
q.push(s);
dis[s] = 0; flag[s] = true;
while (!q.empty()) {
int u = q.front(); q.pop(); flag[u] = false;
for (int i = 0; i < a[u].size(); i++) {//扫描所有邻接点
if (dis[a[u][i].v] > dis[u] + a[u][i].w) {
dis[a[u][i].v] = dis[u] + a[u][i].w;
if (!flag[a[u][i].v]) {
q.push(a[u][i].v);
flag[a[u][i].v] = true;
}
}
}
}
} void Astar(int s, int t) {
if (s == t)k++;//没有这句会T
if (dis[s] == inf){ printf("-1\n"); return; }//没有这句会T
priority_queue<node>q;
q.push(node(s, 0, 0));
int cnt = 0;
while (!q.empty()) {
node h = q.top(); q.pop();
if (h.id == t) {
if (++cnt == k) {
printf("%d", h.f);//返回第k短路
return;
}
}
for (int i = 0; i < b[h.id].size(); i++) {
q.push(node(b[h.id][i].v, h.g + b[h.id][i].w + dis[b[h.id][i].v], h.g + b[h.id][i].w));
}
}
printf("-1\n"); return;
} int main() {
a.resize(maxn);
b.resize(maxn);
scanf("%d%d%d", &n, &m, &k);
scanf("%d%d", &s, &t);
int u, v, w;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
spfa(t);
Astar(s, t);
return 0;
}

A*模板(求K短路)(POJ2449)的更多相关文章

  1. P2483 【模板】k短路([SDOI2010]魔法猪学院)

    题目背景 感谢@kczno1 @X_o_r 提供hack数据 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界 ...

  2. bellman-ford算法求K短路O(n*m),以及判负环O(n*m)

    #include<iostream> #include<algorithm> #include<cstring> using namespace std; cons ...

  3. Luogu P2483 【模板】k短路([SDOI2010]魔法猪学院)

    说实话,看到这道题的洛谷评级我傻了(传说中的最高难度) 然后看完题目才确定这真的是一道k短路的裸题. 也就敲了个A*吧,15分钟竟然没有调试一遍过. 欧洲玄学. 看题目,主要是找几条从1走到n的路加起 ...

  4. BZOJ 1975 魔法猪学院(A*求K短路)

    显然每次贪心的走最少消耗的路径即可.那么也就是找出最短路,次短路,,,K短路之后消耗E的能量的最多的路径条数. 也就是裸的A*算法. #include <bits/stdc++.h> us ...

  5. 【洛谷 P2483】 【模板】k短路([SDOI2010]魔法猪学院)(A*)

    题目链接 优先队列bfs第一次出队就是最短路,那么显然第k次出队就是k短路 ?????????????????????????????? 书上写的 但是直接优先队列bfs会T,所以用A*优化就行,估价 ...

  6. A*算法求K短路模板 POJ 2449

    #include<cstdio> #include<queue> #include<cstring> using namespace std; const int ...

  7. 【模板】K短路 A-star

    引理:当一个状态对应的节点第K次从堆中取出时,该状态对应的当前代价是从起点到该点的第K优解. 代码如下 /* POJ2449 */ #include <cstdio> #include & ...

  8. luogu2483 【模板】k短路([SDOI2010]魔法猪学院)

    模板题 #include <iostream> #include <cstring> #include <cstdio> #include <queue> ...

  9. 第K短路模板【POJ2449 / 洛谷2483 / BZOJ1975 / HDU6181】

    1.到底如何求k短路的? 我们考虑,要求k短路,要先求出最短路/次短路/第三短路……/第(k-1)短路,然后访问到第k短路. 接下来的方法就是如此操作的. 2.f(x)的意义? 我们得到的f(x)更小 ...

随机推荐

  1. RFC笔记—IP Version 6 Addressing Architecture

    IP Version 6 Addressing Architecture,RFC4291 It includes the basic formats for the various types of ...

  2. 【全集】大数据Linux基础

    课程介绍 本课程是由猎豹移动大数据架构师,根据公司大数据平台的运维情况,精心设计和打磨的大数据必备Linux课程.通过本课程的学习大数据新手能够少走弯路,快速掌握Linux常用命令及Shell编程,为 ...

  3. React之this绑定

    一.首先看一下没有绑定this的情况 class App extends React.Component{ constructor(props){ super(props) console.log(' ...

  4. laravel web server设置远程访问及原理

    laravel中可以用命令行php artisan serve 启动web server,并通过localhost:8000访问项目. 但是因为开发环境为虚拟机部署项目,然后通过端口访问,所以开启服务 ...

  5. Apache Log4j 反序列化代码执行(CVE-2019-17571) 漏洞分析

    Apache Log4j 漏洞分析 仅用于研究漏洞原理,禁止用于非法用途,后果自负!!! CVE-2019-17571 漏洞描述 Log4j是美国阿帕奇(Apache)软件基金会的一款基于Java的开 ...

  6. Android Studio无法下载sdk的问题

    参考自:解决Android Studio无法下载sdk的问题 国内网站无法登进google,android sdk无法下载. 尝试使用FQ,重装软件都没有成功. 最后找到了解决办法:http://pi ...

  7. linux 查看系统资源使用信息的一些命令集合

    linux上的进程查看及管理工具: pstree,ps,pidof,pgrep,top,htop,glances,pmap,vmstat,dstat,kill,pkill,job,bg,fg,nohu ...

  8. 【读书笔记】https://source.android.google.cn/devices/bootloader

    https://source.android.google.cn/devices/bootloader 本文主要记录aosp官网关于bootloader的相关资料 Bootloader A bootl ...

  9. HDFS基本命令fs的使用操作

    HDFS(Hadoop Distributed File System)就是hadoop分布式文件系统,fs是操作HDFS文件的一个常用命令. 1.hadoop fs -help 查看fs使用帮助 2 ...

  10. 5种PHP生成图片验证码实例

    5种PHP生成图片验证码实例,包括数字验证码.数字+字母验证码.中文验证码.仿google验证码和算术验证码,PHP生成验证码的原理:通过GD库,生成一张带验证码的图片,并将验证码保存在Session ...