【洛谷4009】汽车加油行驶问题(SPFA乱搞)
大致题意:给定一个\(N*N\)的方形网格,其中1表示这个格子有油库,0表示这个格子没油库,且汽车加满油可以行驶\(k\)条网格边。如果遇到油库必须加满油并花费\(A\)元,如果\(X\)坐标或\(Y\)坐标减少需花费\(B\)元,若需新建一个油库需花费\(C\)元(另需加油费\(A\)元)。问你从\((1,1)\)到\((N,N)\)的最少花费。
\(SPFA\)做法
先说明,这篇博客只讲\(SPFA\),不讲网络流。
我们可以用\(dis_{i,j,l}\)来表示到达网格\((i,j)\),还能行驶\(l\)条网格边所需的最小花费。
显然,初始化\(dis_{1,1,k}=0\),然后从\((1,1)\)出发跑最短路即可。
对于当前状态\((i,j,l)\),我们可以这样考虑它的转移:
如果当前还能行驶的距离不等于\(k\)(即油未加满)
如果当前网格有油库,那么我们就可以花费\(A\)元将状态转移至\((i,j,k)\),即:
\[dis_{i,j,k}=min(dis_{i,j,k},dis_{i,j,l}+A)
\]如果当前网格没有油库,那么我们就可以花费\(C\)元造一个油库,然后花费\(A\)元将状态转移至\((i,j,k)\),即:
\[dis_{i,j,k}=min(dis_{i,j,k},dis_{i,j,l}+A+C)
\]
如果当前还能行驶的距离大于0
- 如果是向右或向下行驶,那么可以直接将状态转移至\((i+1,j,l-1)\)和\((i,j+1,l-1)\),即:
\[dis_{i+1,j,l-1}=min(dis_{i+1,j,l-1},dis_{i,j,l})
\]\[dis_{i,j+1,l-1}=min(dis_{i,j+1,l-1},dis_{i,j,l})
\]如果是向左或向上行驶,那么就需要花费\(B\)元才能将状态转移至\((i-1,j,l-1)\)和\((i,j-1,l-1)\),即:
\[dis_{i-1,j,l-1}=min(dis_{i-1,j,l-1},dis_{i,j,l}+B)
\]\[dis_{i,j-1,l-1}=min(dis_{i,j-1,l-1},dis_{i,j,l}+B)
\]
这样,代码就不难写了吧。
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define N 100
#define K 10
#define MOD (N*N*K)
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
const int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int n,m,a,b,c,s[N+5][N+5],dis[N+5][N+5][K+5],Inqueue[N+5][N+5][K+5];
struct Status
{
int x,y,v;
}q[MOD+5];
inline void read(int &x)
{
x=0;static char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void read_digit(int &x)
{
while(!isdigit(x=tc()));
x-=48;
}
inline void write(int x)
{
if(x>9) write(x/10);
pc(x%10+'0');
}
int main()
{
register int i,j,l,H=Inqueue[1][1][m]=1,T=1;
for(read(n),read(m),read(a),read(b),read(c),i=1;i<=n;++i) for(j=1;j<=n;++j) read_digit(s[i][j]);
for(i=1;i<=n;++i) for(j=1;j<=n;++j) for(l=0;l<=m;++l) dis[i][j][l]=1e9;//初始化
dis[1][1][m]=0,q[1]=(Status){1,1,m};//初始化
while((H%=MOD)^(T+1))//只要队列不为空(因为是手写的循环队列,因此看起来特别别扭)
{
Status k=q[H++];Inqueue[k.x][k.y][k.v]=0;//取出队首元素
if(k.v^m)//如果油未加满
{
if(s[k.x][k.y])//如果这里有油库
{
if(dis[k.x][k.y][k.v]+a<dis[k.x][k.y][m])
{
dis[k.x][k.y][m]=dis[k.x][k.y][k.v]+a;
if(!Inqueue[k.x][k.y][m]) Inqueue[k.x][k.y][m]=1,q[(++T)%=MOD]=(Status){k.x,k.y,m};
}
continue;
}//否则就没有油库,需要花C元建一个
if(dis[k.x][k.y][k.v]+a+c<dis[k.x][k.y][m])
{
dis[k.x][k.y][m]=dis[k.x][k.y][k.v]+a+c;
if(!Inqueue[k.x][k.y][m]) Inqueue[k.x][k.y][m]=1,q[(++T)%=MOD]=(Status){k.x,k.y,m};
}
}
if(k.v)//如果还有油
{
for(i=0;i<4;++i)//枚举上下左右四个方向
{
static int nx,ny;
if(dis[k.x][k.y][k.v]+(dx[i]<0||dy[i]<0)*b<dis[nx=k.x+dx[i]][ny=k.y+dy[i]][k.v-1])//如果是向左或向上,还需加上B元
{
dis[nx][ny][k.v-1]=dis[k.x][k.y][k.v]+(dx[i]<0||dy[i]<0)*b;
if(!Inqueue[nx][ny][k.v-1]) Inqueue[nx][ny][k.v-1]=1,q[(++T)%=MOD]=(Status){nx,ny,k.v-1};
}
}
}
}
register int ans=1e9;
for(i=0;i<=m;++i) ans=min(ans,dis[n][n][i]);//枚举到达(N,N)后还能行驶的距离,从而求出最优方案下的最少花费
return write(ans),fwrite(pp,1,pp_,stdout),0;
}
【洛谷4009】汽车加油行驶问题(SPFA乱搞)的更多相关文章
- 洛谷 P4009 汽车加油行驶问题 解题报告
P4009 汽车加油行驶问题 题目描述 给定一个\(N×N\)的方形网格,设其左上角为起点◎,坐标(1,1) ,\(X\)轴向右为正,\(Y\)轴向下为正,每个方格边长为1 ,如图所示. 一辆汽车从起 ...
- 洛谷P4009 汽车加油行驶问题
题目描述 给定一个 N \times NN×N 的方形网格,设其左上角为起点◎,坐标(1,1)(1,1),XX 轴向右为正, YY 轴向下为正,每个方格边长为 11 ,如图所示. 一辆汽车从起点◎出发 ...
- 洛谷P4009 汽车加油行驶问题(分层最短路)
传送门 说好的网络流24题呢……上次是状压dp,这次怎么又最短路了…… 不过倒是用这题好好学了一下分层图最短路 把每一个位置$(x,y)$,油量剩余$k$表示为一个状态,然后转化成一个$n$进制数,这 ...
- 洛谷P4009汽车加油行驶问题——网络流24题(最短路)
题目:https://www.luogu.org/problemnew/show/P4009 网络流24题中不是网络流的最短路题: 把每个点拆成各个油量上的点,根据要求连边即可: 注意:点数最大为10 ...
- 洛谷 P4009 汽车加油行驶问题 【最小费用最大流】
分层图,建k层,设(i,j,0)为点(i,j)的满油状态,全图的流量都是1,因为重复走到一个点没有意义.如果当前点是加油站,那么它向它上左的点连费用为a的边,向下右连费用为a+b的边: 否则,这个点的 ...
- 洛谷P5211 [ZJOI2017]字符串(线段树+乱搞)
题面 传送门 题解 为什么大佬们全都是乱搞的--莫非这就是传说中的暴力能进队,乱搞能AC-- 似乎有位大佬能有纯暴力+玄学优化\(AC\)(不算上\(uoj\)的\(Hack\)数据的话--这要是放到 ...
- 洛谷 P1600 天天爱跑步(LCA+乱搞)
传送门 我们把每一条路径拆成$u->lca$和$lca->v$的路径 先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x] ...
- P4009 汽车加油行驶问题
P4009 汽车加油行驶问题 最短路 清一色的spfa....送上一个堆优化Dijkstra吧(貌似代码还挺短) 顺便说一句,堆优化Dj跑分层图灰常好写 #include<iostream> ...
- 【题解】【网络流24题】汽车加油行驶问题 [P4009] [Loj6223]
[题解][网络流24题]汽车加油行驶问题 [P4009] [Loj6223] 传送门:汽车加油行驶问题 \([P4009]\) \([Loj6223]\) [题目描述] 给出一个 \(N \times ...
- 【网络流24题】 No.15 汽车加油行驶问题 (分层图最短路i)
[题意] 问题描述:给定一个 N*N 的方形网格,设其左上角为起点◎, 坐标为( 1, 1), X 轴向右为正, Y轴向下为正, 每个方格边长为 1, 如图所示. 一辆汽车从起点◎出发驶向右下角终点▲ ...
随机推荐
- smix到底是个啥?Perl的正则表达式匹配模式
最近在研究一个perl项目,临时学习了一下perl语法,强行看项目源码.因为总是见到各种正则表达式后面接smxi之类,虽然知道是匹配模式,但脑子里毫无概念.所以特地去学习了一下. 以上为背景. Per ...
- [sql Server]除非另外还指定了TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效
今天遇到一个奇怪的问题,项目突然要从mysql切换到sql server数据库,包含order by 子句的嵌套子查询报错. 示例:select top 10 name,age,sex from ( ...
- 3、kvm配置vnc
配置kvm通过vnc访问 virsh edit privi-server 添加如下配置: <graphics type='vnc' port='5901' autoport='no' liste ...
- nagios部署配置流程
nagios部署配置流程 nagios服务端:1.部署nagios服务端(参考nagios官方部署文档).nagios-plugin.php.apache2 2.需要在服务端添/etc/hosts中添 ...
- PDO中构建事务处理的应用程序
<meta http-equiv="Content-Type" content="text/html";charse="utf-8" ...
- Tomcat从socket到java Servlet
整体架构图 一. 启动阶段 BootStrap的main方法加载server.xml配置文件,封装成Server,Service,Connector,Engine等java对象 Server初始化== ...
- Jmeter4.0----HTTP Cookie管理器_抓取cookie中的参数(13)
1.说明 请求结束后,要通过登录用户的JSESSIONID判断用户是否登录成功 2.步骤 第一步:添加 HTTP Cookie管理器 录制前,创建”线程组”,线程组=>配置元件=>HTTP ...
- 【ACM】吝啬的国度 - DFS (图)
吝啬的国度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市, ...
- 11g 配置 dgmgrl 以及报错 DataGuard ORA-00313,
1参考 https://gavinsoorma.com/2010/03/11g-data-guard-broker-dgmgrl-configuration-quick-steps/ This not ...
- mysql日常使用总结(持续更新中)
记录一些日常的mysql常用的使用, 方便随用随查. 一.表结构 1.1 查看表结构 方式1: 可以查看建表语句,完整的表结构. show create table table_name; 方式2:可 ...