升降梯上
大意
n层塔,m个按钮,每次拉拉杆上下电梯,拉拉杆需1s,上下一层需2s,求最小的上升到顶层的时间
思路
虽然看起来不像,但我们可以用最短路中的分层图来思考,遍历每个点以及每个拉杆所上下的楼层,将当前楼层与拉过拉杆所在的楼层相连接,权值为拉杆的位置,连完边之后,跑一遍dijkstra求出最短路即可。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=108600;
struct note
{
int to,next,val;
}edge[N];
int head[N],cnt=0;
void add(int x,int y,int z)
{
edge[++cnt].to=y;
edge[cnt].val=z;
edge[cnt].next=head[x];
head[x]=cnt;
}
LL dis[N],bs[N];
bool vis[N];
priority_queue<pair<int,int> > q;
int n,m,c[N],ss;
void dij()
{
for(int i=1;i<=1086;i++) dis[i]=100086;
memset(vis,0,sizeof(vis));
dis[1]=0;
bs[1]=ss;
q.push(make_pair(0,1));
while(q.size())
{
int x=q.top().second;
q.pop();
if(vis[x]==1) continue;
vis[x]=1;
int now=bs[x];
for(int i=head[x];i;i=edge[i].next)
{
int y=edge[i].to;
if(dis[y]>dis[x]+2*abs(y-x)+abs(edge[i].val-now))
{
dis[y]=dis[x]+2*abs(y-x)+abs(edge[i].val-now);
bs[y]=edge[i].val;
q.push(make_pair(-dis[y],y));
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&c[i]);
if(c[i]==0) ss=i;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i+c[j]<=0||i+c[j]>n||c[j]==0) continue;
add(i,i+c[j],j);
}
}
dij();
if(dis[n]!=100086) printf("%d\n",dis[n]);
else printf("-1\n");
return 0;
}