zoukankan      html  css  js  c++  java
  • 【最短路】【spfa】小vijos P1447 Updown

    小vijos P1447 Updown

    背景

    开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘
    的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手
    柄。
    faebdc 之塔一共有 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

    时间限制

    各个测试点1s

    注释

    样例说明
    手柄从第二个槽扳到第三个槽(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

    显然根据题意,可以dp,但是我们很难转移,所以,我们把所有状态当成点,建边,跑最短路即可。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 #define M 400001
     7 #define N 25001
     8 queue<int>q;
     9 int n,m,a[21],en,v[M],w[M],first[M],next[M],num[1001][21],sta,ans=2147483647,dis[N];
    10 bool inq[N];
    11 int Abs(const int &x){return x<0 ? (-x) : x;}
    12 void AddEdge(const int &U,const int &V,const int &W)
    13 {
    14     v[++en]=V;
    15     w[en]=W;
    16     next[en]=first[U];
    17     first[U]=en;
    18 }
    19 void spfa(const int &s)
    20 {
    21     memset(dis,0x7f,sizeof(dis));
    22     q.push(s); inq[s]=1; dis[s]=0;
    23     while(!q.empty())
    24       {
    25           int U=q.front();
    26           for(int i=first[U];i;i=next[i])
    27             if(dis[v[i]]>dis[U]+w[i])
    28               {
    29                 dis[v[i]]=dis[U]+w[i];
    30                 if(!inq[v[i]])
    31                   {
    32                     inq[v[i]]=1;
    33                     q.push(v[i]);
    34                   }
    35               }
    36           q.pop(); inq[U]=0;
    37       }
    38 }
    39 int main()
    40 {
    41     scanf("%d%d",&n,&m);
    42     for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    43     for(int i=1;i<=n;i++)
    44       for(int j=1;j<=m;j++)
    45         {
    46           num[i][j]=++en;
    47           if(i==1&&a[j]==0) sta=en;
    48         } en=0;
    49     for(int i=1;i<=n;i++)
    50       for(int j=1;j<=m;j++)//单层移动手柄
    51         for(int k=1;k<=m;k++)
    52           if(j!=k)
    53             AddEdge(num[i][j],num[i][k],Abs(j-k));
    54     for(int i=1;i<=n;i++)
    55       for(int j=1;j<=m;j++)
    56         if(a[j]!=0&&i+a[j]>=1&&i+a[j]<=n)
    57           AddEdge(num[i][j],num[i+a[j]][j],(Abs(a[j])<<1));
    58     spfa(sta);
    59     for(int i=1;i<=m;i++) ans=min(ans,dis[num[n][i]]);
    60     printf("%d
    ",ans>=2000000000 ? -1 : ans);
    61     return 0;
    62 }
  • 相关阅读:
    hdu 6702 ^&^ 位运算
    hdu 6709 Fishing Master 贪心
    hdu 6704 K-th occurrence 二分 ST表 后缀数组 主席树
    hdu 1423 Greatest Common Increasing Subsequence 最长公共上升子序列 LCIS
    hdu 5909 Tree Cutting FWT
    luogu P1588 丢失的牛 宽搜
    luogu P1003 铺地毯
    luogu P1104 生日
    luogu P1094 纪念品分组
    luogu P1093 奖学金
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4115081.html
Copyright © 2011-2022 走看看