Processing math: 100%

1340C.Nastya and Unexpected Guest(最短路+dp+01BFS优化)

题意:

一条路长度为n

从0出发,有m个站点

绿灯红灯交替变换

绿灯的时候必须走

从一个站点出来后方向不能变

红灯的时候必须站在一个站点上

求最短多少时间可以到达n点

题解:

定义f(i,j)为到第i个站点时,绿灯当前时间为j,经过了最少轮数红绿灯变色

那么f(i,j)可以往后转移

f(i1,j+x) f(i+1,j+y) f(i,0)

根据题意写转移即可。

这个转移方程要求的是最少轮数,所以就是一个广义的最短路模型。但是这题直接跑nlogm的最短路是会被卡掉的。

这里介绍一种基于01图的最短路求解方法,用双端队列代替优先队列做一个01BFS,时间复杂度是O(n+m)

//定义f(i,j)为到第i个站点时,绿灯当前时间为j,经过了最少轮数红绿灯变色
//那么f(i,j)可以往后转移
//f(i-1,j+x) f(i+1,j+y) f(i-1,0) f(i+1,0)
#include<bits/stdc++.h>
using namespace std;
int n,m,g,r;
int f[10100][1010];
int vis[10100][1010];
int a[10100];
struct qnode {
int x;
int y;
qnode (int xx,int yy) {
x=xx;
y=yy;
}
};
long long bfs () {
deque<qnode> q;
q.push_back(qnode(0,0));
vis[0][0]=1;
long long ans=1e18;
while (q.size()) {
qnode tt=q.front();
q.pop_front();
if (tt.y==0) {
//如果当前绿灯时间刚刚开始
//看看能不能直接走到终点
int t1=n-a[tt.x];
if (t1<=g) {
long long tmp=1ll*f[tt.x][tt.y]*(g+r)+t1;
ans=min(ans,tmp);
}
}
if (tt.y==g) {
if (!vis[tt.x][0]) {
f[tt.x][0]=f[tt.x][tt.y]+1;
vis[tt.x][0]=1;
q.push_back(qnode(tt.x,0));
}
continue;
}
if (tt.x>1) {
//如果不在1号点
//可以往回走
int x=tt.x-1;
int y=tt.y+a[tt.x]-a[x];
if (y<=g&&!vis[x][y]) {
vis[x][y]=1;
f[x][y]=f[tt.x][tt.y];
q.push_front(qnode(x,y));
}
}
if (tt.x<m) {
//如果不在m号点
//可以往后走
int x=tt.x+1;
int y=tt.y+a[x]-a[tt.x];
if (y<=g&&!vis[x][y]) {
vis[x][y]=1;
f[x][y]=f[tt.x][tt.y];
q.push_front(qnode(x,y));
}
}
}
if (ans==1e18) ans=-1;
return ans;
}
int main () {
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d",a+i);
scanf("%d%d",&g,&r);
sort(a+1,a+m+1);
printf("%lld\n",bfs());
}
posted @   zlc0405  阅读(101)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 2025成都.NET开发者Connect圆满结束
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络
点击右上角即可分享
微信分享提示