【模板篇】k短路 SDOI2010 魔法猪学院
题目の传送门
都成了一道模板题了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 魔法猪学院的更多相关文章
- 洛谷 K短路(魔法猪学院)
A*+迪杰特斯拉... 第十一个点卡爆 不管了 #include<iostream> #include<algorithm> #include<cstring> # ...
- Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1357 Solved: 446[Submit][Statu ...
- K短路 (A*算法) [Usaco2008 Mar]牛跑步&[Sdoi2010]魔法猪学院
A*属于搜索的一种,启发式搜索,即:每次搜索时加一个估价函数 这个算法可以用来解决K短路问题,常用的估价函数是:已经走过的距离+期望上最短的距离 通常和Dijkstra一起解决K短路 BZOJ1598 ...
- [BZOJ1975][SDOI2010]魔法猪学院(k短路,A*)
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2748 Solved: 883[Submit][Statu ...
- bzoj1975: [Sdoi2010]魔法猪学院【k短路&A*算法】
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2446 Solved: 770[Submit][Statu ...
- bzoj 1975: [Sdoi2010]魔法猪学院 [k短路]
1975: [Sdoi2010]魔法猪学院 裸题... 被double坑死了 #include <iostream> #include <cstdio> #include &l ...
- [SDOI2010]魔法猪学院(A*,最短路)
[SDOI2010]魔法猪学院(luogu) Description 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig ...
- BZOJ_1975_[Sdoi2010]魔法猪学院_A*
BZOJ_1975_[Sdoi2010]魔法猪学院_A* Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPi ...
- bzoj 1975 [Sdoi2010]魔法猪学院
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1758 Solved: 557[Submit][Statu ...
随机推荐
- Selenium3 + Python3自动化测试系列八——警告框处理和下拉框选择
警告框处理 在WebDriver中处理JavaScript所生成的alert.confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confi ...
- string中的stringstream
博客: 加速:ios::sync_with_stdio(false); 举个例子: 題目:输入的第一行有一个数字 N 代表接下來有 N 行资料,每一行资料里有不固定个数的整数(最多20个,每行最大20 ...
- mysql数据库中某字段一部分乱码
笔者问题:mysql表(表中数据就是乱码,可能是插入时编码问题,这个问题以后解决)导出excel时数据中有乱码(但是在页面上查看是正常的),我们希望能导出一份没有中文乱码的excel 根据热力站中一次 ...
- AutoFac mvc和WebAPI 注册Service (接口和实现)
AutoFac mvc和WebAPI 注册Service (接口和实现) 1.准备组件版本:Autofac 3.5.0 Autofac.Integration.Mvc 3.3.0.0 (I ...
- CKEditor与CKFinder学习--自定义界面及按钮事件捕获
原文地址:CKEditor与CKFinder学习--自定义界面及按钮事件捕获 讨厌CSDN的广告,吃香太难看! 效果图 界面操作图 原始界面 调整后的界面(删除了flush,表单元素等) 该界面的皮 ...
- 笔记52 Mybatis快速入门(三)
一.更多查询 1.模糊查询 修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat(' ...
- 笔记50 Mybatis快速入门(一)
一.Mybatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- delphi获得文件大小
大概有这些方法可以获得文件大小 FileSizeByName(需要引用IdGlobal单元) GetFileSize FileSize(不能获得正在使用的文件大小) FileSeek TFileStr ...
- 码云挂了,无法访问gitee
解决方式1.修改dns为114.114.114.114 2.hosts文件添加212.64.62.174 gitee.com
- NX二次开发-调系统命令UF_load_library[UFUN调DLL]
此函数可以调DLL,可以调宏,当然也可以调其他内部函数(知道哪个内部函数怎么用的前提下). #include <uf.h> void UFUN_API_Call_DLL(char* dll ...