3765 - 迷之阶梯

通过次数

0

提交次数

0

时间限制 : 1 秒 内存限制 : 128 MB

在经过地球防卫小队的数学家连续多日的工作之后,外星人发的密码终于得以破解。它告诉我们在地球某一处的古老遗迹中,存在有对抗这次灾难的秘密道具。防卫小队立刻派出了一个直升机小分队,迅速赶到了这处遗迹。要进入遗迹,需要通过一段迷之阶梯。登上阶梯必须要按照它要求的方法,否则就无法登上阶梯。它要求的方法有以下三个限制:

    1.如果下一步阶梯的高度只比当前阶梯高1,则可以直接登上。

    2.除了第一步阶梯外,都可以从当前阶梯退到前一步阶梯。

    3.当你连续退下k步后,你可以一次跳上不超过当前阶梯高度+2^k的阶梯。比如说你现在位于第j步阶梯,并且是从第j+k步阶梯退下来的,那么你可以跳到高度不超过当前阶梯高度+ 2^k的任何一步阶梯。跳跃这一次只算一次移动。

    开始时我们在第一步阶梯。由于时间紧迫,我们需要用最少的移动次数登上迷之阶梯。请你计算出最少的移动步数。

题目输入

第1行:一个整数N,表示阶梯步数。

第2行:N个整数,依次为每层阶梯的高度,保证递增。

题目输出

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

输入/输出样例

输入格式

5
0 1 2 3 6

输出格式

7

C++解答

#include <cstdio>
#include <cstring>

using namespace std;

long long high[1000],f[1000];
int n;

int main(){
	scanf("%d",&n);
	memset(f,50,sizeof(f));
	for(int i=1;i<=n;i++){
		scanf("%lld",&high[i]);
	}
	f[1]=0;
	for(int i=2;i<=n;i++){
		if(high[i]==high[i-1]+1){
			f[i]=f[i-1]+1;
		}
		//从哪里退
		for(int j=3;j<=i-1;j++){
			if(f[j]>50000000) continue;
			//枚举退到哪里
			for(int k=1;k<=j-2;k++){
				long long tmp=f[j]+j-k+1;
				long long kf=(1LL)<<(j-k);
				if(high[k]+kf>=high[i]&&tmp<f[i]){
					f[i]=tmp;
				} 
			} 
		} 
	}
	if(f[n]>50000000){
		printf("-1");
	}
	else{
		printf("%lld",f[n]);
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}