1 条题解
-
0
牛逼题。
初看这题,毫无思路,再看数据范围,这么小!那我们完全可以把每个巴士经过的路线全部存下来。
于是我们模拟每个巴士的路线,然后对于每个点 ,记录所有经过它的巴士和该巴士到达这个点的最小时间。然后注意到巴士有一个周期,后面也要用到所以存下来。
然后你跑一遍最短路,对于每个点 ,若你到达这个点的时间为 ,你想要等经过这个点的某辆公交车,这辆公交车运行的周期为 ,这辆公交车第一次到达这个点的时间为 ,那么我们要求最小的非负整数 使得:
那么易得:
由于要求非负,所以我们要给它取模后加上一个 ,于是就变成了:
$$\begin{aligned}w=((s-t)\bmod c+c)\bmod c \end{aligned}$$注意一定要先取模再加,至于为什么,可以看这篇帖子。
然后就做完了,你每个点松弛一下然后判断一下是否无解即可。
::::success[AC code]
#include<bits/stdc++.h> using namespace std; #define int long long const int N=2010,inf=1e9; int dis[N][N],point[N][N];//第一个到达这个点的是谁 struct edge{ int x,y,w; }; int H,W,n,stx,sty,enx,eny; bool operator < (const edge &xx,const edge &yy){ return xx.w>yy.w; } priority_queue<edge> q; struct node{ int x,y,T,d,id;//走一次的周期,这辆公交第一次到达(x,y)这个位置的最小时间 }; vector<node> g[N][N];//每个点的所有公交车 void dj(){ for(int i=1;i<=H;i++){ for(int j=1;j<=W;j++){ dis[i][j]=inf; } } dis[stx][sty]=0; q.push({stx,sty,0}); while(q.size()){ int x=q.top().x,y=q.top().y; if(dis[x][y]<q.top().w){ q.pop();continue; } if(x==enx&&y==eny)break; q.pop(); for(auto tmp:g[x][y]){ int nx=tmp.x,ny=tmp.y,c=tmp.T; int s=tmp.d,id=tmp.id; int w=((s-dis[x][y])%c+c)%c;//在这个位置等到下一班车的时间 if(!w&&id!=point[x][y])w+=c;//防止两次都乘同一辆车 if(dis[nx][ny]>dis[x][y]+w+1){//不能立马换乘所以要加一 dis[nx][ny]=dis[x][y]+w+1; point[nx][ny]=id; q.push({nx,ny,dis[nx][ny]}); } } } if(dis[enx][eny]==inf)dis[enx][eny]=-1; cout<<dis[enx][eny]<<"\n"; } signed main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>H>>W>>stx>>sty>>enx>>eny; cin>>n; for(int i=1,a,b,c,d,t;i<=n;i++){ cin>>a>>b>>c>>d>>t; int C=(c-a+d-b)*2;//周长,走一圈的周期 t=(C-t)%C; for(int j=a;j<=c-1;j++){//存公交车路线 g[j][b].push_back({j+1,b,C,t,i}); t=(t+1)%C; } for(int j=b;j<=d-1;j++){ g[c][j].push_back({c,j+1,C,t,i}); t=(t+1)%C; } for(int j=c;j>=a+1;j--){ g[j][d].push_back({j-1,d,C,t,i}); t=(t+1)%C; } for(int j=d;j>=b+1;j--){ g[a][j].push_back({a,j-1,C,t,i}); t=(t+1)%C; } } dj(); return 0; }::::
- 1
信息
- ID
- 8988
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者