题目の传送门

都成了一道模板题了OvO

==============================================================================

吐槽时间

不想看的自行点目录

今天才发现自己还没有学A*
就去看了一下A*寻路, 但是只看也不行啊, 得找题练一练啊..
然后上luogu搜A*算法结果找到了这道题?
但这不应该是道图论么= =
然后看了看题解发现原来是最短路预处理然后A*
那就写嘛, 写的有模有样的大约30min?
然后过了样例, 交上去30pts, 其余RE..
然后改数组大小再交 40pts MLE…
蛤? 然后又改一遍, 40pts RE…
什么鬼咯… 然后发现自己根本tm没调用dij()这个函数…
也就是没预处理, 直接搜的, 突然觉得40pts很不错了2333
然后调用dij()就开始恒输出0了. 结果发现刚开始要反向建边?
然后就xjb改, 因为怕MLE还删掉一些数组重复利用之类的…
后来终于又过了样例 然后交上去0pts 9WA1RE…
Emmmm又是什么锅啊…
冷静分析了一波, 发现自己dij往里加点的时候是这么加的:

hp[sz++]=(zt){d[e[i].to],0,d[e[i].to]};

这tm还能过样例??????????
然后改完就能70pts RE了.
然后改两波数组大小就终于AC了.
然而要是省选干出这种事就死透了.. 最多通过对拍搞个70吧? (没准直接M掉滚粗了Emmmm

==============================================================================

题目分析

好了吐槽时间结束, 我们来看看这道题.
都说了是k短路模板, 题意就是求1->n的前k短路的长度和不超过m, 求最大的k.
我们就进行bfs, 第k次搜到n搜到的就是最短路.
但是朴素的bfs很显然是过不了的, 我们要采用启发式搜索(A*).

感觉A*好像比数论什么的要有用... 现实生活中用到A*的场合也是非常多的, 比如游戏中角色的自动寻路啊之类的都要用到A*不是...(然后再吐槽一句在markdown里打多个A*的话会出现玄学的斜体...

A*的基本形式: f(x)=g(x)+h(x), 其中
- f(x)表示从起始状态到结束状态的估价
- g(x)表示从起始状态到当前状态已经花费的代价.
- h(x)自然就是表示从当前状态到结束状态的估价咯~

其中A*算法的核心就是一个合适的h(x)的选择.
- 如果h(x)比实际值要小, 那么能得到最优解, 但是搜索范围较大, 效率较低.
- 如果h(x)比实际值要大, 那么搜索范围较小, 速度快, 但不一定能取得最优解.
- 而如果h(x)恰好等于实际值, 那么搜索将按照最优解进行, 是我们最想看到的一种情况.
- 所以我们要尽可能让自己选的h(x)接近实际值.

很幸运的是, 在k短路这个问题中, 我们刚好能取到完美地等于实际值的h(x),
我们只需要把边反向, 从终点开始求一波单源最短路就ok了.. (而且好像这题不卡spfa…

A*的过程中总是要找到f值最小的优先进行扩展, 我们就写个堆就好了..
这里倾情推荐algorithm库里的push_heap和pop_heap函数, 不管开不开O2都快的飞起, 比手写堆都快, 不知道怎么实现的.
(而且这题据说用priority_queue会MLE的说~
我们每次搜到n就用E减去这条路的长度, 如果E<0就输出当前的k就好了.

怎么说呢 这题还不能算是特别正宗的A*, 因为也不需要记录什么openset closeset, 也不需要输出路径所以不需要记录父亲之类的, 所以就这样吧…

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=5050;
const int M=2e5+8;
struct edge{int to,next;double data;}e[M]; int v[N],tot;
inline void buildedge(const int&x,const int&y,const double&z){
e[++tot].to=y;e[tot].data=z;e[tot].next=v[x];v[x]=tot;
}
struct zt{double f,g;int x;}hp[M<<3]; int sz;
inline bool operator<(const zt&a,const zt&b){return a.f>b.f;}
double d[N],Z[M],K; int n,m,X[M],Y[M];
void dij(){
for(int i=1;i<n;++i) d[i]=1e12;
d[n]=0; hp[sz++]=(zt){0,0,n};
while(sz){
::pop_heap(hp, hp+sz); zt x=hp[--sz];
if(d[x.x]<x.f) continue;
for(int i=v[x.x];i;i=e[i].next)
if(d[x.x]+e[i].data<d[e[i].to]){
d[e[i].to]=d[x.x]+e[i].data;
hp[sz++]=(zt){d[e[i].to],0,e[i].to};
::push_heap(hp, hp+sz);
}
}
}
int Astar(int s=0){
hp[sz++]=(zt){d[1],0,1};
while(sz){
::pop_heap(hp, hp+sz); zt x=hp[--sz];
if(x.f>K) break;
for(int i=v[x.x];i;i=e[i].next){
hp[sz++]=(zt){x.g+e[i].data+d[e[i].to],x.g+e[i].data,e[i].to};
::push_heap(hp, hp+sz);
}
if(x.x==n){
K-=x.f; if(K<0) break; ++s;
}
}
return s;
}
int main(){
scanf("%d%d%lf",&n,&m,&K);
for(int i=1;i<=m;++i){
scanf("%d%d%lf",&X[i],&Y[i],&Z[i]);
::buildedge(Y[i], X[i], Z[i]);
} dij();
::memset(e, 0, sizeof e);
::memset(v, 0, sizeof v); tot=0;
for(int i=1;i<=m;++i)
::buildedge(X[i], Y[i], Z[i]);
printf("%d",Astar());
}

以后数组算着空间够的话数组一定能开大就开大….
当然还是一定要避免MLE… 毕竟数组开小了还能得个部分分, MLE就直接爆零滚粗了(ノ`Д)ノ

【模板篇】k短路 SDOI2010 魔法猪学院的更多相关文章

  1. 洛谷 K短路(魔法猪学院)

    A*+迪杰特斯拉... 第十一个点卡爆 不管了 #include<iostream> #include<algorithm> #include<cstring> # ...

  2. Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1357  Solved: 446[Submit][Statu ...

  3. K短路 (A*算法) [Usaco2008 Mar]牛跑步&[Sdoi2010]魔法猪学院

    A*属于搜索的一种,启发式搜索,即:每次搜索时加一个估价函数 这个算法可以用来解决K短路问题,常用的估价函数是:已经走过的距离+期望上最短的距离 通常和Dijkstra一起解决K短路 BZOJ1598 ...

  4. [BZOJ1975][SDOI2010]魔法猪学院(k短路,A*)

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2748  Solved: 883[Submit][Statu ...

  5. bzoj1975: [Sdoi2010]魔法猪学院【k短路&A*算法】

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2446  Solved: 770[Submit][Statu ...

  6. bzoj 1975: [Sdoi2010]魔法猪学院 [k短路]

    1975: [Sdoi2010]魔法猪学院 裸题... 被double坑死了 #include <iostream> #include <cstdio> #include &l ...

  7. [SDOI2010]魔法猪学院(A*,最短路)

    [SDOI2010]魔法猪学院(luogu) Description 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig ...

  8. BZOJ_1975_[Sdoi2010]魔法猪学院_A*

    BZOJ_1975_[Sdoi2010]魔法猪学院_A* Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPi ...

  9. bzoj 1975 [Sdoi2010]魔法猪学院

    1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1758  Solved: 557[Submit][Statu ...

随机推荐

  1. babel/core 6.x升级到7.x要碰到的一些坑

    刚学习react.js没多久,碰到各种坑.就比如这个问题,弄了我3个小时,终于解决了.其实就是一个小问题. 报错信息: Error: Cannot find module '@babel/core' ...

  2. C#内嵌Python架构实现

    C#通过IronPython内嵌Python脚本,实现了对业务逻辑抽象及判断,适合在大量订单需要进行校验的场合使用. 比如,贷款时会对用户进行核查,核查过程可能存在多个节点,并且节点可能会随着政策而不 ...

  3. Editor REST Client

    Editor REST Client 制作一个http请求 请求行 GET https://example.com/comments/1 HTTP/1.1 POST https://example.c ...

  4. 尝试修改源码需要用到git存一下

    git reflog查看本地记录 git reset --hard 02a3260

  5. 关于windows和linux系统更换JDK版本后,修改环境变量也无法生效的原因和解决办法

    今天遇到了一个问题: 我linux系统之前安装JDK12,今天将其改成了JDK1.8,并修改了环境变量,但是通过java -version命令显示的依旧是JDK12的版本. 这是因为,当使用安装版本的 ...

  6. Django项目从新建到运行

    返回主目录:Django框架 内容目录: 一.安装之前 二.Django安装 三.创建项目 四.配置 一.安装之前 安装django之前你需要注意的几个事项: 1.版本问题 建议使用1.11.11左右 ...

  7. WXML 数据绑定

  8. 了解GTIN小记

    GTIN为条形码,即"全球贸易项目代码"(Global Trade Item Number ) GTIN用作识别商品品项的全球性独一编码,是编码系统中应用最广泛的标识代码. GTI ...

  9. jq-demo-购物车

    首页 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title& ...

  10. 使用Sonatype Nexus搭建Maven私服后,如何添加第三方JAR包

    使用Sonatype Nexus搭建Maven私服后如何添加第三方JAR包 步骤如下 1.打开nexus地址,进行登录 2.登录Nexus后,点击右侧的“Repositories”,显示当前Nexus ...