古老的牛市,遗迹的天梯(一道水题好多坑)

古老的牛市,遗迹的天梯
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述

牛市,一个拥有悠久历史的城市,2333年考古学家在牛市发现了一个神秘的遗迹,这些勇敢而智慧的古队员准备进入这个遗迹,但要进入这个遗迹就需要通过一段天梯。而登上天梯必须要按照它要求的方法,否则就无法登上。它要求的方法为:

1.可以直接登上比当前位置高1个单位高度的天梯。

2.可以从当前阶梯往下退一级天梯(第一级天梯除外)。

3.在连续退k步后,跳跃一次,跳跃的高度不超过2^k。比如说你现在位于第i级天梯,且之前从第i+k级天梯退下来,此时你可以跳到高度不超过(当前高度+ 2^k)的任何一级天梯。每一次跳跃只算一次移动哦!

开始的时候考古小队在第一级天梯。请你计算出最少的移动步数以登上最高一级天梯。

为何考古搞得跟游戏历险一样?牛市一定是一个魔性的城市!
输入描述:

第1行:一个整数N,表示天梯级数。

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

输出描述:

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

示例1
输入
复制

5
0 1 2 3 6

输出
复制

7

说明

1≤N≤2001 \leq N \leq 2001≤N≤200。 每级阶梯高度不超过231−12^{31}-1231−1。

#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<iostream>
using namespace std;

long long f[60],dp[205],s[205];
int main()
{
	int n;
	f[0] = 1;
	for (int i = 1; i <= 42; i++)
	{
		f[i] =f[i-1]* 2;
	}
	for (int i = 1; i <= 205; i++)
		dp[i] = 1e16;
	
	cin >> n;
	dp[1] = 0;
	for (int i = 1; i <= n; i++)
		cin >> s[i];
	for (int i = 2; i <= n; i++)
		for (int j = i-1; j >0; j--)
		{
			if (s[i] - s[j] == 1)
				dp[i] = dp[j] + 1;
			else {
				
				for (int k = j-1; k >0&&k>j-31; k--)
				{
					
					if (s[i] - s[k] <= f[j - k])
					{
						dp[i] = min(dp[i], dp[j] + j - k + 1);
					
					}
				}
			}
		}
	if (dp[n] >= 1e16/2)
		dp[n] = -1;
	cout << dp[n] << endl;

}
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const int N=2e2+10;
ll a[N],dp[N],f[N];
int n;
int main()
{
    f[0]=1;rep(i,1,40) f[i]=f[i-1]*2;
 
    n=read(); rep(i,1,n) a[i]=read(),dp[i]=1e14;
 
 
    dp[1]=0;
    for(int i=2;i<=n;++i){
 
        int flag=0;
        for(int j=i-1;j>=1;--j){
 
            for(int k=0;k<i-j&&k<41;++k){
                if(a[j]+f[k]>=a[i]){
 
                    dp[i]=min(dp[i],dp[j+k]+k+1);
                    flag=1;
                }
            }
 
        }
 
 
        if(!flag) {puts("-1");return 0;}
    }
 
    printf("%d\n",dp[n]);
 
 
}
/*
5
0 1 2 3 100
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值