开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。
Nescafe之塔一共有N层,升降梯在每层都有一个停靠点。手柄有M个控制槽,第i个控制槽旁边标着一个数Ci,满足
。如果Ci>0,表示手柄扳动到该槽时,电梯将上升Ci层;如果Ci<0,表示手柄扳动到该槽时,电梯将下降-Ci层;并且一定存在一个Ci=0,手柄最初就位于此槽中。注意升降梯只能在1~N层间移动,因此扳动到使升降梯移动到1层以下、N层以上的控制槽是不允许的。
电梯每移动一层,需要花费2秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费1秒钟时间。探险队员现在在1层,并且想尽快到达N层,他们想知道从1层到N层至少需要多长时间?
输入格式
第一行两个正整数N、M。
第二行M个整数C1、C2……CM。
输出格式
输出一个整数表示答案,即至少需要多长时间。若不可能到达输出-1。
提示
手柄从第二个槽扳到第三个槽(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<
。
样例数据
输入样例 #1
6 3
-1 0 2
输出样例 #1
19
这题比较有意思哈。乍看之下的确有最短路的感觉,但是感觉有不太一样,因为发现即使到达一个点以后手柄的状态也可能会不一样,那么就点和手柄的位置合起来组合成一个点来做就好啦,也就是说,一个点有两个信息来确定的,那么总点数就是
,边数小于
,用spfa或者那个什么斯塔拉算法都可以嘛。跑一下就好了,图都不用建,不过re了好多次。
这里我用那个什么斯特拉算法,因为感觉写的不多,所以熟悉一下。
代码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
public class Main
{
static int dis[][]=new int[20][1005];
static boolean vis[][]=new boolean[20][1005];
static int solve()
{
PriorityQueue<Node> que=new PriorityQueue<Node>(11,new Comparator<Node>()
{
@Override
public int compare(Node o1, Node o2) {
// TODO Auto-generated method stub
return o1.d-o2.d;
}
});
for(int i=0;i<m;i++)
{
Arrays.fill(dis[i], Integer.MAX_VALUE);
Arrays.fill(vis[i], false);
}
dis[now][1]=0;
que.add(new Node(1,now,0));
while(!que.isEmpty())
{
Node temp=que.poll();
//System.out.println("haha");
int u=temp.to;
int cur=temp.cur;
if(vis[cur][u])
continue;
vis[cur][u]=true;
for(int i=0;i<m;i++)
{
int to=u+d[i];
if(to<1||to>n)
continue;
int cost=Math.abs(i-cur)+2*Math.abs(d[i]);
if(dis[i][to]>temp.d+cost)
{
dis[i][to]=temp.d+cost;
que.add(new Node(to,i,dis[i][to]));
}
}
}
int ans=Integer.MAX_VALUE;
for(int i=0;i<m;i++)
ans=Math.min(ans, dis[i][n]);
if(ans==Integer.MAX_VALUE)
return -1;
return ans;
}
static int n,m,now;
static int d[]=new int[20];
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
for(int i=0;i<m;i++)
{
d[i]=sc.nextInt();
if(d[i]==0)
now=i;
}
System.out.println(solve());
}
}
class Node
{
int to,cur,d;
Node(int _to,int _cur,int _d)
{
to=_to;
cur=_cur;
d=_d;
}
}