迷之阶梯(ladder.???)

迷之阶梯(ladder.???)

问题描述:

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

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

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

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

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

输入格式:

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

第 2 行:N 个整数(每两个之间有 1 个空格),依次为每层阶梯的高度,保证递增。

输出格式:

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

输入样例:

5 0 1 2 3 6

输出样例:

7

样例解释:

连续凳 3 步,再后退 3 步,然后直接跳上去。

数据限制: 对于 50%的数据:1 <= N <= 20;

对于 100%的数据:1 <= N <= 200;每步阶梯高度不超过 2^31-1。

dp

#include<bits/stdc++.h>
using namespace std;
long long dp[100005];
long long a[100005];
long long ksm(long long x,long long k)
{
    long long n=1;
    while(k)
    {
        if(k&1)n*=x;
        x*=x;
        k>>=1;
    }
    return n;
}
int main()
{
    freopen("ladder.in","r",stdin);
    freopen("ladder.out","w",stdout);
    long long n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        dp[i]=999999999;
    }
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    dp[1]=0;
    if((a[2]-a[1])==1)
    dp[2]=1;
    else 
    {
        cout<<-1;
        return 0;
    }
    for(int i=3;i<=n;i++)
    {
        for(int j=1;j<i-1;j++)
        {
            for(int k=j+1;k<=i-1;k++)
            {
                if(ksm(2,k-j)>=a[i]-a[j])
                {
                    dp[i]=min(dp[i],dp[j]+(dp[k]-dp[j])+(k-j)+1);
                }
            }
        }
        if((a[i]-a[i-1])==1)dp[i]=min(dp[i-1]+1,dp[i]);
    }
    if(dp[n]==999999999)
    cout<<-1;
    else
    cout<<dp[n];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wenjie2002/article/details/81208074