P3259 [JLOI2014] 路径规划 题解
P3259 [JLOI2014] 路径规划
如此分层图好题做的人却不多,不知为何。
红绿灯的期望通过时间
省流:
首先标签带一个 数学
的原因就是在于红绿灯期望通过时间的计算。由于我们可以在任意时刻进入这个红绿灯,由于一个红绿灯的周期是
,此时不需要等,期望通过时间为 ; ,此时需要等的时间为 。
于是容易得到对于任意的
但是我们不会积分,于是考虑作出函数图象
这个东西就是这么来的。
知道了每个红绿灯的期望通过时间,考虑直接把这个时间加到这个点出边的边权里,这个部分就解决了。
分层图最短路
考虑分层图的原因是:本题的最短路有两个限制:油量的限制
但是分层图最短路只能解决一个限制,不妨先解决红绿灯,因为
如果没有油量的限制,我们直接从第零层的起点跑最短路,最后在终点的各个层统计
这个新图也是有
时间复杂度方面,由于原图有
#include<bits/stdc++.h>
using namespace std;
constexpr int MAXN=1.1e6+5;
constexpr double INF=156842099845.0,eps=1e-10;
int n,m,k,limit,cost,S,T;
int id[11][MAXN/10];
unordered_map<string,int>mp;
vector<int>gas;
double out[MAXN];
struct{
int head[MAXN],tot;
struct{
int v,to;
double w;
}e[MAXN<<1];
void addedge(int u,int v,double w){
e[++tot]={v,head[u],w};
head[u]=tot;
}
void addf(int u,int v,double w){
if(fabs(out[v])>eps)
for(int i=0;i<k;i++)
addedge(id[i][u],id[i+1][v],w+out[v]);
else
for(int i=0;i<=k;i++)
addedge(id[i][u],id[i][v],w);
}
double dis[MAXN];
bool vis[MAXN];
void dijkstra(int s){
memset(dis,0x42,(n*(k+1)+1)<<3); // double也是可以memset的哦!
memset(vis,0,n*(k+1)+1);
priority_queue<pair<double,int>>q;
dis[s]=0;
q.emplace(0,s);
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u],v;i;i=e[i].to)
if(dis[v=e[i].v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
q.emplace(-dis[v],v);
}
}
}
}G,GF; // G原图,GF新图
int main(){
cin.tie(nullptr)->sync_with_stdio(0);
cin>>n>>m>>k>>limit>>cost;
for(int i=0;i<=k;i++)
for(int j=1;j<=n;j++)
id[i][j]=i*n+j;
for(int i=1;i<=n;i++){
string s;
int a,b;
cin>>s>>a>>b;
mp[s]=i;
if(s=="start"||s=="end"||s.find("gas")!=string::npos) gas.emplace_back(i);
if(s=="start") S=i;
else if(s=="end") T=i;
if(a) out[i]=1.0*a*a/2/(a+b);
}
for(int i=1;i<=m;i++){
string u,v,fk;
int w;
cin>>u>>v>>fk>>w;
G.addf(mp[u],mp[v],w);
G.addf(mp[v],mp[u],w);
}
for(auto x:gas){
G.dijkstra(id[0][x]);
for(auto y:gas){
if(x==y) continue;
int w=(x!=S&&x!=T?cost:0);
for(int i=0;i<=k;i++)
if(G.dis[id[i][y]]<=limit)
for(int j=0;i+j<=k;j++)
GF.addedge(id[j][x],id[i+j][y],G.dis[id[i][y]]+w);
}
}
GF.dijkstra(id[0][S]);
double ans=INF;
for(int i=0;i<=k;i++) ans=min(ans,GF.dis[id[i][T]]);
cout<<fixed<<setprecision(3)<<ans<<'\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】