D e s c r i p t i o n Description Description
有
n
n
n阶楼梯
你现在在第一阶楼梯
你的目标是第
n
n
n阶楼梯
每一个楼梯都有高度
H
[
i
]
H[i]
H[i]
且为升序
你有三个操作
1、如果你前面的楼梯比你所在的楼梯的高度高1,你就走到下一阶
2、你可以后退一阶
3、在你最近的k步里,你都在后退,你现在在i阶,你可以跳到j阶
(
i
<
j
,
H
[
j
]
−
H
[
i
]
<
=
2
k
)
(i<j,H[j]-H[i]<=2^k)
(i<j,H[j]−H[i]<=2k)
上述操作各为一步
现在要求要多少步才能到达目标
I n p u t Input Input
两行,第一行为
n
n
n
第二行为
1
−
n
1-n
1−n阶楼梯的高度
O u t p u t Output Output
一行,为最少步数,如果不能到达,则输出-1
S a m p l e I n p u t Sample Input SampleInput
5
0 1 2 3 6
S a m p l e O u t p u t Sample Output SampleOutput
7
思路
DP
见代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int A[55],F[55],M[55];
int n;
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d%d",&n,&A[1]);
F[1]=0;
for(int i=2;i<=n;++i)
{
scanf("%d",&A[i]);
F[i]=1e9;
if(A[i]-1==A[i-1] && F[i-1]!=1e9)F[i]=F[i-1]+1;
}
M[1]=2;
for(int i=2;i<=30;++i)M[i]=M[i-1]*2;
for(int i=2;i<=n-1;++i)//枚举退步前
if(F[i]!=1e9)//如果可以到达
{
for(int k=1;k<=i-1;++k)//枚举退了几步
for(int j=i+1;j<=n;++j)//枚举退步后跳到第几个台阶
if(A[j]-A[i-k]<=M[k])//满足条件
F[j]=min(F[j],F[i]+k+1);
for(int i=2;i<=n;++i)//判断可以往前走的
if(A[i]-1==A[i-1] && F[i-1]!=1e9)
F[i]=min(F[i],F[i-1]+1);
}
if(F[n]!=1e9)printf("%d",F[n]);
else printf("-1") ;
}