Date:2022.03.15
题目描述
在经过地球防卫小队的数学家连续多日的工作后,外星人发的密码终于得以破解。它 告诉我们在地球某一处的古老遗迹中,存在有对抗这次灾难的秘密武器。防卫小队立即赶 到这处遗迹。要进入遗迹,需要通过一段迷之阶梯。登上阶梯必须要按照它要求的方法, 否则就无法登上阶梯。它要求的方法有以下三个限制:
如果下一步阶梯的高度只比当前阶梯高 1,则可以直接登上。
除了第一步阶梯外,都可以从当前阶梯退到前一步阶梯。
当你连续退下 k 后,你可以一次跳上不超过当前阶梯高度 +
2
k
2^k
2k 的阶梯。比如说你现 在位于第 j 步阶梯,并且是从第 j+k 步阶梯退下来的,那么你可以跳到高度不超过当前阶 梯高度+
2
k
2^k
2k
的任何一步阶梯。跳跃这一次只算一次移动。
开始时我们在第一步阶梯,由于时间紧迫,我们需要用最少的移动次数登上迷之阶梯。 请你计算出最少的移动步数。
输入格式
第一行:一个整数 N,表示阶梯步数。
第二行:N 个整数,依次为每层阶梯的高度,保证递增。
输出格式
第一行:一个整数,如果能登上阶梯,输出最小步数,否则输出-1。
输入输出样例
输入 #1复制
5
0 1 2 3 6
输出 #1复制
7
说明/提示
【样例解释】
连续登 3 步,再后退 3 步,然后直接跳上去。
【数据范围】
对于 50%的数据:1≤N≤20。
对于 100%的数据:1≤N≤200。
对于 100%的数据:每步阶梯高度不超过 2^31-1
思路①:wa,但是大体思路是对的。
f
[
i
]
:
f[i]:
f[i]:登上
i
i
i个阶梯所需最小步数。
状态转移方程:
①
a
[
i
]
=
=
a
[
i
−
1
]
+
1
时
(
即
一
步
能
到
下
一
格
)
:
f
[
i
]
=
m
i
n
(
f
[
i
]
,
f
[
i
−
1
]
+
1
)
;
a[i]==a[i-1]+1时(即一步能到下一格):f[i]=min(f[i],f[i-1]+1);
a[i]==a[i−1]+1时(即一步能到下一格):f[i]=min(f[i],f[i−1]+1);
代码如下:
②一般情况(不论一步能不能到下一格):此时显然可退到任意格,再跳到第
i
i
i格,因此枚举由
i
−
1
i-1
i−1(
i
i
i的上一步,也是当前所在点,这也正是问题所在,开始以为只能在当前所在点往前退hh)。因此只需枚举退到的点
j
【
j
∈
[
1
,
i
−
2
]
】
,
j【j\in[1,i-2]】,
j【j∈[1,i−2]】,
f
[
i
]
=
m
i
n
(
f
[
i
]
,
f
[
i
−
1
]
+
(
i
−
1
−
j
+
1
)
)
【
在
(
1
<
<
(
i
−
1
−
j
)
)
+
a
[
j
]
>
=
a
[
i
]
前
提
下
】
f[i]=min(f[i],f[i-1]+(i-1-j+1))【在(1<<(i-1-j))+a[j]>=a[i]前提下】
f[i]=min(f[i],f[i−1]+(i−1−j+1))【在(1<<(i−1−j))+a[j]>=a[i]前提下】。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long LL;
LL n,m,p,k,t,a[N],sum[N],f[N];
int main()
{
cin>>n;
memset(f,0x3f,sizeof f);f[1]=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++)
{
if(a[i]==a[i-1]+1) f[i]=min(f[i-1]+1,f[i]);
for(int j=1;j<=i-2;j++)
if((1<<(i-1-j))+a[j]>=a[i])
f[i]=min(f[i],f[i-1]+(i-1-j+1));
}
if(f[n]!=0x3f3f3f3f3f3f3f3f) cout<<f[n];
else cout<<"-1";
return 0;
}
思路②:显然1漏判了,因为后退再跳可能是从任意点后退再跳到
i
i
i的,而并非只是从
i
−
1
i-1
i−1。因此我们考虑从每个点
j
【
j
∈
[
1
,
i
−
1
]
】
j【j\in[1,i-1]】
j【j∈[1,i−1]】后退
k
【
k
∈
[
1
,
j
−
1
]
】
k【k\in[1,j-1]】
k【k∈[1,j−1]】步再跳到
i
i
i的情况。(思想一样不贴方程了
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
typedef long long LL;
LL n,m,p,k,t,a[N],sum[N],f[N];
int main()
{
cin>>n;
memset(f,0x3f,sizeof f);f[1]=0;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++)
{
if(a[i]==a[i-1]+1) f[i]=min(f[i-1]+1,f[i]);
for(int j=1;j<=i-1;j++)
for(int k=1;k<=j-1;k++)
if((1<<(k))+a[j-k]>=a[i])
f[i]=min(f[i],f[j]+k+1);
}
if(f[n]!=0x3f3f3f3f3f3f3f3f) cout<<f[n];
else cout<<"-1";
return 0;
}