题目の传送门

都成了一道模板题了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. Selenium3 + Python3自动化测试系列八——警告框处理和下拉框选择

    警告框处理 在WebDriver中处理JavaScript所生成的alert.confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confi ...

  2. string中的stringstream

    博客: 加速:ios::sync_with_stdio(false); 举个例子: 題目:输入的第一行有一个数字 N 代表接下來有 N 行资料,每一行资料里有不固定个数的整数(最多20个,每行最大20 ...

  3. mysql数据库中某字段一部分乱码

    笔者问题:mysql表(表中数据就是乱码,可能是插入时编码问题,这个问题以后解决)导出excel时数据中有乱码(但是在页面上查看是正常的),我们希望能导出一份没有中文乱码的excel 根据热力站中一次 ...

  4. AutoFac mvc和WebAPI 注册Service (接口和实现)

    AutoFac  mvc和WebAPI  注册Service (接口和实现) 1.准备组件版本:Autofac 3.5.0    Autofac.Integration.Mvc 3.3.0.0  (I ...

  5. CKEditor与CKFinder学习--自定义界面及按钮事件捕获

    原文地址:CKEditor与CKFinder学习--自定义界面及按钮事件捕获  讨厌CSDN的广告,吃香太难看! 效果图 界面操作图 原始界面 调整后的界面(删除了flush,表单元素等) 该界面的皮 ...

  6. 笔记52 Mybatis快速入门(三)

    一.更多查询 1.模糊查询 修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat(' ...

  7. 笔记50 Mybatis快速入门(一)

    一.Mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...

  8. delphi获得文件大小

    大概有这些方法可以获得文件大小 FileSizeByName(需要引用IdGlobal单元) GetFileSize FileSize(不能获得正在使用的文件大小) FileSeek TFileStr ...

  9. 码云挂了,无法访问gitee

    解决方式1.修改dns为114.114.114.114 2.hosts文件添加212.64.62.174   gitee.com

  10. NX二次开发-调系统命令UF_load_library[UFUN调DLL]

    此函数可以调DLL,可以调宏,当然也可以调其他内部函数(知道哪个内部函数怎么用的前提下). #include <uf.h> void UFUN_API_Call_DLL(char* dll ...