开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。
塔一共有 N 层,升降梯在每层都有一个停靠点。
手柄有 M 个控制槽,第 i 个控制槽旁边标着一个数 C**i,满足 C1<C2<C3<…<C M。
如果 C**i>0,表示手柄扳动到该槽时,电梯将上升 C**i 层;如果 C**i<0,表示手柄扳动到该槽时,电梯将下降 −C**i 层;并且一定存在一个 C**i=0,手柄最初就位于此槽中。注意升降梯只能在 1∼N 层间移动,因此扳动到使升降梯移动到 1 层以下、N* 层以上的控制槽是不允许的。
电梯每移动一层,需要花费 2 秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费 1 秒钟时间。
探险队员现在在 1 层,并且想尽快到达 N 层,他们想知道从 1 层到 N 层至少需要多长时间?
输入格式
第一行两个正整数 N、M。
第二行 M 个整数 C1、C2…C**M*。
输出格式
输出一个整数表示答案,即至少需要多长时间。
若不可能到达输出 −1。
数据范围
1≤N≤1000,2≤M≤20,−N<C1<C2<…<C**M<N
输入样例:
6 3
-1 0 2
输出样例:
19
久违的一遍ac
额,-1忘记判断了,这个要是在比赛的时候吃上一发罚时可受不了
总体就是一个dp的思路,而如果用普通的dp写的话,因为停止条件的原因,会有很多的不必要的时间复杂度。
比较dijkstra本身就是dp,所以其实加维度什么的都没问题。
直接给dijkstra加维度来计算边权就可以了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
struct edge
{
int next,to,v;
}e[200001];
int head[200001],tot;
inline void add(int i,int j,int v)
{
e[++tot].next=head[i];
e[tot].to=j;
e[tot].v=v;
head[i]=tot;
}
int n,m,dist[1001][21],vis[1001][21],c[21],s;
void dijkstra()
{
priority_queue<pair<int,pair<int,int> > ,vector<pair<int,pair<int,int> > >,greater<pair<int,pair<int,int> > > > q;
q.push({0,{s,1}});
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[1][s]=0;
while(!q.empty())
{
int x=q.top().second.second;
int y=q.top().second.first;
q.pop();
if(vis[x][y]==1)continue;
vis[x][y]=1;
for(int i=head[x];i!=0;i=e[i].next)
{
int u=e[i].to;
int v=abs(e[i].v-y)+abs(u-x)*2;
if(dist[u][e[i].v]>dist[x][y]+v)
{
dist[u][e[i].v]=dist[x][y]+v;
q.push({dist[u][e[i].v],{e[i].v,u}});
}
}
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n=read();m=read();
for(int i=1;i<=m;i++)
{
c[i]=read();
if(c[i]==0)s=i;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(i+c[j]>=1&&i+c[j]<=n&&c[j]!=0)add(i,i+c[j],j);
}
}
dijkstra();
int ans=0x3f3f3f3f;
for(int i=1;i<=m;i++)
{
ans=min(ans,dist[n][i]);
}
if(ans!=1061109567)
cout<<ans<<endl;
else
cout<<-1<<endl;
return 0;
}
没啥好说的。
感觉上一题学到的更多