迷之階梯(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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章