D87 分层图最短路 Dijkstra 算法 UVa1078 Steam Roller
D87 分层图最短路 Dijkstra 算法 UVa1078 Steam Roller_哔哩哔哩_bilibili
Steam Roller - UVA 1078 - Virtual Judge
给一个带边权的方格图,沿直线匀速运动,边权不变。转向前后,因为速度需要变为 0,所以转向前后的边权加倍。
当然连接起点和终点的边权也要加倍,注意,一条边两端的速度均为 0 时,边权仅加倍。求起点到终点的最短路。

思路
连边与点的状态有关,点有向上、向右、向下、向左和静止 五种状态,所以把每个点拆成 5 个点
给格点按行列编号,写个开点函数 id(x,y)=(x-1)*C+y,再令 n=R*C,那么,
每个格点的五个拆点依次为:id(x,y),id(x,y)+n,id(x,y)+2∗n,id(x,y)+3∗n,id(x,y)+4∗n
起点 (r1,c1) 和终点 (r2,c2) 都是静止点,所以 s = id(r1,c1)+4*n,t = id(r2,c2)+4*n
建图分四种情况:
- 同向的动点到动点连边,边权为 w
- 同向的静点到动点连边,边权为 2w
- 同向的动点到静点连边,边权为 2w
- 同向的静点到静点连边,边权为 2w

点数 N = 100*100*5 = 5e4,边数 M = 100*100*4*4 = 16e4
相关板子:
D75【模板】分层图最短路 Dijkstra 算法 P4568 [JLOI2011] 飞行路线 - 董晓 - 博客园
// 分层图最短路 Dijkstra 算法 O(Mlogn) #include<bits/stdc++.h> using namespace std; const int N=50010,M=16e4; const int dx[]={-1,0,1,0},dy[]={0,1,0,-1}; //上,右,下,左 int idx,h[N],ne[M],to[M],ww[M]; void add(int u,int v,int w){ to[++idx]=v,ww[idx]=w,ne[idx]=h[u],h[u]=idx; } int R,C,r1,c1,r2,c2,n,s,t; int d[N]; bool vis[N]; int G[105][105][4]; void Dijkstra(){ memset(d,0x3f,sizeof(d)),d[s]=0; memset(vis,0,sizeof(vis)); priority_queue<pair<int,int> >q; q.push({0,s}); while(!q.empty()){ int u=q.top().second; q.pop(); if(vis[u])continue; vis[u]=true; for(int i=h[u]; i; i=ne[i]){ int v=to[i],w=ww[i]; if(d[v]>d[u]+w){ d[v]=d[u]+w; q.push({-d[v],v}); } } } } int id(int x,int y){ //格点的编号 return (x-1)*C+y; } int main(){ if(scanf("%d %d %d %d %d %d",&R,&C,&r1,&c1,&r2,&c2)==EOF||!R) return 0; n=R*C; s=id(r1,c1)+4*n; t=id(r2,c2)+4*n; //起点编号,终点编号 memset(G,0,sizeof(G)); memset(h,0,sizeof(h)); idx=0; for(int i=1,t;i<=R;++i){ for(int j=1;j<C;++j)scanf("%d",&t),G[i][j][1]=G[i][j+1][3]=t; //[i,j]右侧 [i,j+1]左侧的横边 if(i!=R)for(int j=1;j<=C;++j)scanf("%d",&t),G[i][j][2]=G[i+1][j][0]=t; //[i,j]下面 [i+1,j]上面的竖边 } for(int x=1;x<=R;++x)for(int y=1;y<=C;++y){ for(int t=0;t<4;++t){ //上0,右1,下2,左3 int nx=x+dx[t],ny=y+dy[t]; if(nx<1||nx>R||ny<1||ny>C) continue; int w=G[x][y][t]; if(!w) continue; add(id(x,y)+t*n,id(nx,ny)+t*n,w); //同向的动点到动点连边 add(id(x,y)+t*n,id(nx,ny)+4*n,2*w); //同向的动点到静点连边 add(id(x,y)+4*n,id(nx,ny)+t*n,2*w); //同向的静点到动点连边 add(id(x,y)+4*n,id(nx,ny)+4*n,2*w); //同向的静点到静点连边 } } Dijkstra(); static int Case=0; printf("Case %d: ",++Case); if(d[t]==0x3f3f3f3f) printf("Impossible\n"); else printf("%d\n",d[t]); main(); }
浙公网安备 33010602011771号