古老的牛市,遗迹的天梯
时间限制: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
*/