3806 -- 【模拟试题】升降梯上
Description
开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。
Nescafe之塔一共有N层,升降梯在每层都有一个停靠点。手柄有M个控制槽,第i个控制槽旁边标着一个数Ci,满足 C1<C2<C3<....<CM。如果Ci>0,表示手柄扳动到该槽时,电梯将上升Ci层;如果Ci<0,表示手 柄扳动到该槽时,电梯将下降 -Ci 层;并且一定存在一个Ci=0,手柄最初就位于此槽中。注意升降梯只能在1~N层间移动,因此扳动到使升降梯移动到1层以下、N 层以上的控制槽是不允许的。
电梯每移动一层,需要花费2秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费1秒钟时间。探险队员现在在1层,并且想尽快到达N层,他们想知道从1层到N层至少需要多长时间?
Input
第一行两个正整数N、M。
第二行M个整数C1、C2......CM。
Output
输出一个整数表示答案,即至少需要多长时间。若不可能到达输出-1。
Sample Input
6 3 -1 0 2
Sample Output
19
Hint
【样例说明】
手柄从第二个槽扳到第三个槽(0扳到2),用时1秒,电梯上升到3层,用时4秒。
手柄在第三个槽不动,电梯再上升到5层,用时4秒。
手柄扳动到第一个槽(2扳到-1),用时2秒,电梯下降到4层,用时2秒。
手柄扳动到第三个槽(-1扳倒 2),用时2秒,电梯上升到6层,用时4秒。
总用时为(1+4)+4+(2+2)+(2+4)=19秒。
【数据规模】
对于30%的数据,满足1≤N≤10,2<=M<=5。
对于100%的数据,满足1≤N≤1000,2<=M<=20,-N<C1<C2<....<CM<N。
方法1:记忆化搜索,但是只能得90分,可能是我写丑了。。。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,c[25],cur,f[1005],ans=0x3f3f3f3f;
inline int Abs(int x)
{
if(x<0)x=-x;
return x;
}
int dfs(int pos,int ti,int now)
{
if(ti<=f[pos])f[pos]=ti;
else return f[pos];
for(int i=1;i<=m;i++)
{
if(pos+c[i]>n||pos+c[i]<1||i==cur)continue;
f[pos+c[i]]=min(f[pos+c[i]],dfs(pos+c[i],ti+Abs(i-now)+Abs(c[i])*2,i));
}
return f[pos];
}
int main(){
// freopen("updown.in","r",stdin);
// freopen("updown.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>c[i];
if(c[i]==0)cur=i;
}
memset(f,0x3f,sizeof(f));
f[1]=0;
dfs(1,0,cur);
if(f[n]==0x3f3f3f3f)cout<<-1;
else cout<<f[n];
return 0;
}
方法2:SPFA
d[i][j]表示从1到i点,档位在j的最短距离
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
struct node{int x,y;
}w[1005],q[1000005];
int cur,vis[1005][25],d[1005][25],m,c[25],n;
void spfa()
{
int h=1,t=1;
q[h].x=1,q[h].y=cur;
vis[1][cur]=1,d[1][cur]=0;
while(h<=t)
{
int X=q[h].x,Y=q[h].y;
vis[X][Y]=0;
h++;
for(int i=1;i<=m;i++)
{
if(X+c[i]>=1&&X+c[i]<=n&&d[X+c[i]][i]>d[X][Y]+abs(Y-i)+2*abs(c[i]))
{
d[X+c[i]][i]=d[X][Y]+abs(Y-i)+2*abs(c[i]);
if(!vis[X+c[i]][i])
{
vis[X+c[i]][i]=1;
t++;
q[t].x=X+c[i],q[t].y=i;
}
}
}
}
}
int main(){
cin>>n>>m;
memset(d,0x3f,sizeof(d));
for(int i=1;i<=m;i++)
{
cin>>c[i];
if(c[i]==0)cur=i;
}
spfa();
int ans=0x3f3f3f3f;
for(int i=1;i<=m;i++)
ans=min(ans,d[n][i]);
if(ans==0x3f3f3f3f)cout<<-1;
else cout<<ans;
return 0;
}