• 最短路


                                                                     升降梯上

    内存限制:128 MiB 时间限制:1000 ms 标准输入输出
    题目描述:开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。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层至少需要多长时间?

    输入格式

    第一行两个正整数N、M。

    第二行M个整数C1、C2……CM。

    输出格式

    输出一个整数表示答案,即至少需要多长时间。若不可能到达输出-1。

    样例

    样例输入

    6 3
    -1 0 2
    

    样例输出

    19
    

    数据范围与提示

    手柄从第二个槽扳到第三个槽(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。

    思路:建边,将时间当作边权用spfa求最短路,将二维的点弄成一维

    (可以用dp,但因为可以下降,所以有后效性,不能包括所有的状态,必须循环跑dp直到答案不变)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=20000+10,maxm=5e5+10,inf=0x3f3f3f3f;
    int a[maxn];
    struct Edge{
       int to,next,w;
    }e[maxm];
    int head[maxm],tot=0;
    void Insert(int a,int b,int c){
         e[++tot].to=b;
         e[tot].next=head[a];
         e[tot].w=c;
         head[a]=tot;
    }
    bool inq[maxn];
    int d[maxn];
    void spfa(int s){
         memset(d,0x3f,sizeof(d));
         d[s]=0;
         queue<int> q;
         q.push(s);
         inq[s]=1;
         while(!q.empty()){
            int u=q.front();
            q.pop();
            inq[u]=0;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(d[v]>d[u]+e[i].w){
                   d[v]=d[u]+e[i].w;
                   if(!inq[v]){
                      q.push(v);
                      inq[v]=1;
                   }
                }
            }
         }
    }
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        int s;
        for(int i=1;i<=m;i++) {
           scanf("%d",&a[i]);
           if(a[i]==0) s=i;
        }   
        for(int i=1;i<=n;i++){
           for(int j=1;j<m;j++){
              int x=(i-1)*m+j;
              Insert(x,x+1,1);
              Insert(x+1,x,1);
           }
        }
        for(int i=1;i<=n;i++){
           for(int j=1;j<=m;j++){
               int v=i+a[j];
               if(v<1||v>n) continue;
               int x=(i-1)*m+j;
               int y=(v-1)*m+j;
               Insert(x,y,2*abs(a[j]));   
           }
        }
        spfa(s);//因为起点一定是第一行第j列,(1-1)×m+s==s
        int ans=inf;
        for(int i=1;i<=m;i++){
           int x=(n-1)*m+i;
           ans=min(ans,d[x]);
        }//枚举最后一行的扳手位置
        if(ans!=inf) printf("%d
    ",ans);
        else printf("-1
    ");
        return 0; 
    }
    View Code
  • 相关阅读:
    spring杂谈
    mysql
    java集合
    java
    mysql数据库面试题
    replace替换
    移动端拨打电话
    react 获取自定义属性、value等值
    react 框架 安装与梳理
    h5在ios端 input/textarea 输入不了
  • 原文地址:https://www.cnblogs.com/HZOIDJ123/p/13251969.html
Copyright © 2020-2023  润新知