A*算法小记
\(\text{A*}\)
一种启发式搜索
和暴搜的差别是多了一个估价函数,每次取出一个估算最优的状态以期更高效完成任务
重点在于估价函数 \(\text{h*(n)}\) 的设计,若实际代价为 \(\text{h(n)}\),则
若 \(\text{h*(n)=h(n)}\),设计得非常好
若 \(\text{h*(n)<h(n)}\),跑得更快,只是可能搜不出来正确答案
若 \(\text{h*(n)>h(n)}\),慢是慢些,但正确性还有保证
例如 \(k\) 短路
暴搜的话就是找出所有路径,取第 \(k\) 短
但实际上若精准预估当前状态到终止状态的代价,每次取出最小代价状态,
那么 \(k\) 次到达终止状态后,前 \(k\) 短路就已经被搜出来了
显然,估价函数就定为当前状态到终止状态的最短路
这个可以反向建图 \(\text{dijkstra}\) 预处理
\(\text{sample}\)
P2483 【模板】k 短路 / [SDOI2010] 魔法猪学院
$\text{Code}$
#include <cstdio>
#include <queue>
#define RE register
#define IN inline
using namespace std;
const int N = 5005, M = 2e5 + 5, INF = 1e18;
int n, m, cnt[N];
double e;
struct node{
int id; double f, v;
bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q;
struct graph{
struct edge{int to, nxt; double w;}e[M];
int tot, h[N], vis[N]; double dis[N];
IN void add(int u, int v, double w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
IN void getdis()
{
for(RE int i = 1; i < n; i++) dis[i] = INF, vis[i] = 0;
vis[n] = 0, Q.push(node{n, 0});
while (!Q.empty())
{
node x = Q.top(); Q.pop();
if (vis[x.id]) continue;
vis[x.id] = 1;
for(RE int i = h[x.id]; i; i = e[i].nxt)
{
int v = e[i].to;
if (dis[v] > dis[x.id] + e[i].w)
Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
}
}
}
}e1, e2;
int main()
{
scanf("%d%d%lf", &n, &m, &e);
int u, v; double w;
for(RE int i = 1; i <= m; i++) scanf("%d%d%lf", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
e2.getdis(), Q.push(node{1, 0});
int k = (int)e / e2.dis[1], ans = 0;
while (!Q.empty())
{
node x = Q.top(); Q.pop();
++cnt[x.id];
if (x.id == n)
{
e -= x.v;
if (e <= 0){printf("%d\n", ans); return 0;}
++ans;
}
for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
{
int v = e1.e[i].to;
if (cnt[v] < k && x.v + e1.e[i].w + e2.dis[v] <= e)
Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
}
}
printf("%d\n", ans);
}
P2901 [USACO08MAR]Cow Jogging G
$\text{Code}$
#include <cstdio>
#include <queue>
#define RE register
#define IN inline
typedef long long LL;
using namespace std;
const int N = 1005, M = 2e5 + 5, INF = 1e9;
int n, m, k, cnt[N];
struct node{
int id; LL f, v;
bool operator < (const node &c) const{return f > c.f;}
};
priority_queue<node> Q;
struct graph{
struct edge{int to, nxt, w;}e[M];
int tot, h[N], vis[N]; LL dis[N];
IN void add(int u, int v, int w){e[++tot] = edge{v, h[u], w}, h[u] = tot;}
IN void getdis()
{
for(RE int i = 2; i <= n; i++) dis[i] = INF, vis[i] = 0;
vis[1] = 0, Q.push(node{1, 0});
while (!Q.empty())
{
node x = Q.top(); Q.pop();
if (vis[x.id]) continue;
vis[x.id] = 1;
for(RE int i = h[x.id]; i; i = e[i].nxt)
{
int v = e[i].to;
if (dis[v] > dis[x.id] + e[i].w)
Q.push(node{v, dis[v] = dis[x.id] + e[i].w});
}
}
}
}e1, e2;
int main()
{
scanf("%d%d%d", &n, &m, &k);
for(RE int i = 1, u, v, w; i <= m; i++) scanf("%d%d%d", &u, &v, &w), e1.add(u, v, w), e2.add(v, u, w);
e2.getdis(), Q.push(node{n, 0});
int sum = 0;
while (!Q.empty())
{
node x = Q.top(); Q.pop();
++cnt[x.id];
if (x.id == 1)
{
printf("%d\n", x.v), ++sum;
if (sum == k) return 0;
}
for(RE int i = e1.h[x.id]; i; i = e1.e[i].nxt)
{
int v = e1.e[i].to;
if (cnt[v] < k)
Q.push(node{v, x.v + e1.e[i].w + e2.dis[v], x.v + e1.e[i].w});
}
}
for(RE int i = sum; i < k; i++) printf("-1\n");
}
A*算法小记的更多相关文章
- RSA算法小记
学习来源:http://www.cnblogs.com/vamei/p/3480994.html 小记: 一.数学基础: 欧拉Phi函数:Φ(n)=总数(从1到n-1中与n互质的整数) (1)欧拉定理 ...
- <转>Java 常用排序算法小记
排序算法很多地方都会用到,近期又重新看了一遍算法,并自己简单地实现了一遍,特此记录下来,为以后复习留点材料. 废话不多说,下面逐一看看经典的排序算法: 1. 选择排序 选择排序的基本思想是遍历数组的过 ...
- 配对堆优化Dijkstra算法小记
关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...
- Tarjan-LCA算法小记
Tarjan-LCA算法是一种离线算法. 算法描述: DFS遍历每个节点,对于遍历到的当前节点u: ①建立以u为代表元素的集合. ②遍历与u相连的节点v,如果没有被访问过,对于v使用Tarjan-LC ...
- 扩展KMP算法小记
参考来自<拓展kmp算法总结>:http://blog.csdn.net/dyx404514/article/details/41831947 扩展KMP解决的问题: 定义母串S和子串T, ...
- KMP算法小记
Knuth-Morris-Pratt算法: 转载来自http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_ ...
- 【2018.08.01】(表/栈/队列/大小顶堆)学习Stark和Queue算法小记
Train Problem I As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of st ...
- 【2018.07.30】(广度优先搜索算法/队列)学习BFS算法小记
一些BFS参考的博客: https://blog.csdn.net/ldx19980108/article/details/78641127 https://blog.csdn.net/u011437 ...
- 【2018.07.29】(深度优先搜索/回溯)学习DFS算法小记
参考网站:https://blog.csdn.net/ldx19980108/article/details/76324307 这个网站里有动态图给我们体现BFS和DFS的区别:https://www ...
- 【2018.07.28】(字符串/回文串)学习Manacher算法小记
主要是应用在回文串啦,原理也理解了老半天,如果没有图片的话,我也看不太懂它的原理 学习的灵感来源来自于:https://segmentfault.com/a/1190000008484167 /* 最 ...
随机推荐
- 英格索兰扳手网口通信协议EOR原理
前言 前几天遇到这个需求,需要记录扳手每一次的周期数据,但是我不知道通信协议是什么,只知道是一个tcp的连接,问售后,也不给我网口调试软件(英格索兰自己家的软件).经过我俩天的谷歌,终于找到了他们公司 ...
- springMVC环境的搭建(一)
概要: MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller). MV ...
- MybatisPlus多表连接查询一对多分页查询数据
一.序言 在日常一线开发过程中,多表连接查询不可或缺,基于MybatisPlus多表连接查询究竟该如何实现,本文将带你找到答案. 在多表连接查询中,既有查询单条记录的情况,又有列表查询,还有分页查询, ...
- JS执行机制及ES6
一.JS执行机制 JS语言有个特点是单线程,即同一时间只能做一件事.单线程就意味着,所有的任务需要排队,前一个任务结束,才会执行后一个任务,可能造成页面渲染不连贯. 为了解决这个问题,利用多核CPU的 ...
- jmeter Foreach 控制器与json提取器/正则表达式
适用场景:对某些业务数据依次操作 如:删除某个用户下的所有人员数据,无批量删除接口时,只能循环调用删除人员接口,直到删除完成 返回数据格式: 1. 使用json提取器或正则表达式提取业务数据(jso ...
- JavaScript:立即执行函数
想象一下,如果我希望某个代码块,只执行一次,就不再执行,应该怎么办? 代码块肯定是用函数来表示,执行肯定是调用函数,但是确保只执行一次,该怎么办? 我们为什么可以多次调用函数,因为函数名指向了函数的内 ...
- 8、IDEA提交代码出现: Fetch failed fatal: Could not read from remote repository
转载自 第一步.确认Git公钥/密钥是否生成: 1. 首先查看本地是否生成git密钥,一般在C盘home目录下:[C:你自己的home目录\.ssh] 第二步:添加Git密钥: 右键->Git ...
- kafka详解(01) - 概述
kafka详解(01) - 概述 定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(Message Queue),主要应用于大数据实时处理领域. 消息队列 MQ传统应用场景之异步处理 使用消 ...
- YMOI 2019.6.22
题解 YMOI 2019.6.22 lia麦頔溜了,缺了lia麦頔的排名仅供参考 不过分数还是暴露无遗 T1 邪恶入侵 简易题干: 在三维空间内有一些点,点之间有双向边.每一次询问给出一个m,只有边权 ...
- hashlib 模块 subprocess 模块 logging日志模块
今日内容 hashlib加密模块 1.何为加密 将明文数据处理成密文数据 让人看不懂 2.为什么加密 保证数据的安全 3.如何判断数据是否加密的 一串没有规律的字符串(数字.字母.符号) 4.密文的长 ...