最短路之升降梯上
阿新 • • 發佈:2020-07-05
題目
思路
又雙叒叕死在最短路了,這題怎麼看也像dfs啊,然鵝寫掛了,
- 我們把每一層,每一個槽設為圖中每一個點,這樣好像是一個二維矩陣。
- 既然按照最短路的思路來,首先是建圖,建圖。。。。。
這怎麼建??!因為我們平時建圖用的都是一維編號,所以我們把,整個二維壓到一維中去,這裡用一個get函式實現,然後建邊,每一層相鄰的兩個點之間相互建邊,彼此到達,既然是相鄰,那麼時間代價(邊權)就是1,然後就是每兩層之間建邊,
int u=get(i,j),v=get(i+a[j],j);//i表示層數,j表示手柄位置 if(j!=now && (i+a[j])>=1 && (i+a[j])<=n)add(u,v,abs(a[j])*2);
注意兩層之間距離為a[j],而不是1,時間代價為abs(a[j]*2),
- 為了方便處理,最後可以建一條通向點m*n+1的邊,邊權為0,
- 跑一遍最短路即可
最後附上蒟蒻程式碼
#include<bits/stdc++.h> using namespace std; const int maxn=30010; const int maxm=1e6+10; int head[maxn],Next[maxm<<1],ver[maxm<<1],edge[maxm<<1]; int a[maxn]; int tot,now; int n,m; void add(int x,int y,int z){ ver[++tot]=y; edge[tot]=z; Next[tot]=head[x]; head[x]=tot; } int get(int x,int y){ return (x-1)*m+y; } bool v[maxn]; int d[maxn]; priority_queue<pair<int,int > >q; void dij(int s){ memset(d,0x3f,sizeof(d)); d[s]=0; q.push(make_pair(0,s)); while(!q.empty()){ int x=q.top().second; q.pop(); if(v[x])continue; v[x]=1; for(int i=head[x];i;i=Next[i]){ int y=ver[i],z=edge[i]; if(d[y]>d[x]+z){ d[y]=d[x]+z; q.push(make_pair(-d[y],y)); } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d",&a[i]); if(a[i]==0)now=i; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(j<m)add(get(i,j),get(i,j+1),1); if(j>1)add(get(i,j),get(i,j-1),1); int u=get(i,j),v=get(i+a[j],j); if(j!=now && (i+a[j])>=1 && (i+a[j])<=n)add(u,v,abs(a[j])*2); } } for(int i=1;i<=m;i++){ add(get(n,i),n*m+1,0); } dij(get(1,now)); int ans=0x7f7f7f7f; if(d[n*m+1]>=1061109567)printf("-1\n"); else printf("%d\n",d[n*m+1]); return 0; }