zoukankan      html  css  js  c++  java
  • 10.20T6 DP

    Description

      在经过地球防卫小队的数学家连续多日的工作之后,外星人发的密码终于得以破解。它告诉我们在地球某一处的古老遗迹中,存在有对抗这次灾难的秘密道具。防卫小队立刻派出了一个直升机小分队,迅速感到了这处遗迹。要进入遗迹,需要通过一段迷之阶梯。登上阶梯必须要按照它要求方法,否则就无法登上阶梯。它要求的方法有以下三个限制:
      1.如果下一步阶梯的高度只比当前阶梯高1,则可以直接登上。
      2.除了第一步阶梯外,都可以从当前阶梯退到前一步阶梯。
      3.当你连续退下k后,你可以一次跳上不超过当前阶梯高度2^k的阶梯。比如说你现在位于第j步阶梯,并且是从第j + k步阶梯退下来的。那么你可以跳到高度不超过当前阶梯高度+ 2^k的任何一步阶梯。跳跃这一次只算一次移动。
      开始时我们在第1步阶梯。由于时间紧迫,我们需要用最少的移动次数登上迷之阶梯。请你计算出最少的移动步数。

    Input

      第1行:一个整数N,表示阶梯步数
      第2行:N个整数,依次为每层阶梯的高度,保证递增

    Output

      第1行:一个整数,如果能登上阶梯,输出最小步数,否则输出-1

    Sample Input

    5
    0 1 2 3 6

    Sample Output

    7

    Hint

    样例解释:从0到3再返回到0再跳到6

    【数据范围】
      对于50%的数据:1<=N<=20;
      对于100%的数据:1<=N<=200;
      每步阶梯高度不超过2^31-1
     
     
    这题一个经典的麻烦我们的地方在于那个直接往上走一步
    实质上仔细想想会发现其实如果我不后退本就可以上升1个高度
    然后就等同于2了
    然后设f[i]为到第i个台阶的最少步数,接着我们就可以枚举从哪个地方跳下来和跳了多少步
    然后就可以直接dp了
    code:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 int a[10003];
     6 int f[300];
     7 int main() {
     8     int n;
     9     cin>>n;
    10     for(int i=1; i<=n; i++)cin>>a[i];
    11     memset(f,0x3f3f3f3f,sizeof f);
    12     f[1]=0;
    13     for(int i=1; i<=n; i++) {
    14         for(int j=1;j<i;j++){
    15             for(int k=0;k<=min(j-1,31);k++){
    16                 if(a[i]<=a[j-k]+(1<<k))f[i]=min(f[i],f[j]+k+1);
    17             }
    18         }
    19     }
    20     cout<<(f[n]==0x3f3f3f3f?-1:f[n]);
    21     return 0;
    22 }

    转换一下我们如果枚举从那个地方直接跳2^k也是可行的

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 int a[10003];
     6 int f[300];
     7 int main() {
     8     int n;
     9     cin>>n;
    10     for(int i=1; i<=n; i++)cin>>a[i];
    11     memset(f,0x3f3f3f3f,sizeof f);
    12     f[1]=0;
    13     for(int i=1; i<=n; i++) {
    14         for(int j=1;j<i;j++){
    15             for(int k=0;k<i-j;k++){
    16                 if(a[j]+(1<<k)>=a[i])f[i]=min(f[i],f[j+k]+k+1);
    17             }
    18         }
    19     }
    20     cout<<(f[n]==0x3f3f3f3f?-1:f[n]);
    21     return 0;
    22 }

    还有一种官方的奇葩神仙分层图做法

    code:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 typedef long long LL;    
     5 const LL INF=0x7fffffff/2;
     6 LL d[1000005]={0},vst[1000005]={0},lap[2005]={0},n,h[1000005]={0},cnt=0,q[1000005]={0};
     7 struct front_star{int ne,to,v;}a[2500005];
     8 void Addedge(LL x,LL y,LL v)
     9 {   a[++cnt].to=y;a[cnt].ne=h[x];a[cnt].v=v;h[x]=cnt;}
    10 void SPFA(LL u,LL n)
    11 {   LL i,j,k,L=0,R=1;
    12     for(i=1;i<=n;i++)d[i]=INF;d[u]=0;
    13     q[1]=u;vst[u]=1;
    14     while(L!=R)
    15       {L=(L+1)%400005;
    16        i=q[L];vst[i]=0;
    17        for(k=h[i];k;k=a[k].ne)
    18          {j=a[k].to;
    19           if(d[j]>d[i]+a[k].v)
    20             {d[j]=d[i]+a[k].v;
    21              if(!vst[j])
    22                {R=(R+1)%400005;q[R]=j;vst[j]=1;}
    23             }
    24          }
    25       }
    26 }
    27 int main()
    28 {   LL i,j,k,p,D;
    29     scanf("%lld%lld",&n,&lap[1]);
    30     for(i=2;i<=n;i++)
    31       {scanf("%d",&lap[i]);
    32        if(lap[i]-lap[i-1]==1)
    33          for(j=1;j<=n;j++){Addedge((i-1)+(j-1)*n,i,1);}
    34       }
    35     for(k=1;k<=min(n-1,32LL);k++)
    36       {D=(1<<k);
    37        for(i=1;i<=n-k;i++)
    38           for(j=i+1;j<=n;j++)
    39             {if(lap[j]-lap[i]<=D){Addedge(i+k*n,j,1);}
    40              else break;
    41             }
    42       }
    43     for(k=33;k<=n;k++)
    44        for(i=1;i<=n-k;i++)Addedge(i+k*n,n,1);
    45     for(k=1;k<=n-1;k++)for(i=2;i<=n;i++)Addedge(i+(k-1)*n,(i-1)+k*n,1);
    46     SPFA(1,n*n);
    47     if(d[n]==INF)printf("-1");
    48     else printf("%lld",d[n]);
    49     return 0;
    50 }

    over

  • 相关阅读:
    Go语言踩过的坑---记录GOPATH在GOLAND中的坑
    反射小例子
    制作pip包
    mac常用软件安装链接
    YCSB压测elasticsearch
    SSO和Auth2.0
    JAVA内部类的四大作用
    修改fastadmin,添加模糊查询
    AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message
    taro3.x: 封装实现chat emit on
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9823391.html
Copyright © 2011-2022 走看看