首页 > 代码库 > 洛谷P1929 迷之阶梯
洛谷P1929 迷之阶梯
P1929 迷之阶梯
题目描述
在经过地球防卫小队的数学家连续多日的工作后,外星人发的密码终于得以破解。它 告诉我们在地球某一处的古老遗迹中,存在有对抗这次灾难的秘密武器。防卫小队立即赶 到这处遗迹。要进入遗迹,需要通过一段迷之阶梯。登上阶梯必须要按照它要求的方法, 否则就无法登上阶梯。它要求的方法有以下三个限制:
如果下一步阶梯的高度只比当前阶梯高 1,则可以直接登上。
除了第一步阶梯外,都可以从当前阶梯退到前一步阶梯。
- 当你连续退下 k 后,你可以一次跳上不超过当前阶梯高度 的阶梯。比如说你现 在位于第 j 步阶梯,并且是从第 j+k 步阶梯退下来的,那么你可以跳到高度不超过当前阶 梯高度+的任何一步阶梯。跳跃这一次只算一次移动。
开始时我们在第一步阶梯,由于时间紧迫,我们需要用最少的移动次数登上迷之阶梯。 请你计算出最少的移动步数。
输入输出格式
输入格式:第一行:一个整数 N,表示阶梯步数。
第二行:N 个整数,依次为每层阶梯的高度,保证递增。
输出格式:第一行:一个整数,如果能登上阶梯,输出最小步数,否则输出-1。
输入输出样例
输入样例#1:
50 1 2 3 6
输出样例#1:
7
说明
【样例解释】
连续登 3 步,再后退 3 步,然后直接跳上去。
【数据范围】
对于 50%的数据:1≤N≤20。
对于 100%的数据:1≤N≤200。
对于 100%的数据:每步阶梯高度不超过 2^31-1
【题解】
是一个十分显然的DP,而且是一个我显然不会做的DP
【状态定义】F[i]表示跳到第i阶楼梯的最小步数。
【转移】
若h[i] == h[i - 1] + 1 则 F[i] + F[i - 1] + 1
F[i] = min{F[i], F[j + k] + k + 1} 其中k = log2(h[i] - h[j])
【初始状态】
F[1] = 0
【答案】
f[n]
Code
1 #include <bits/stdc++.h> 2 3 inline void read(int &x) 4 { 5 x = 0;char ch = getchar();char c = ch; 6 while(ch > ‘9‘ || ch < ‘0‘)c = ch, ch = getchar(); 7 while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘, ch = getchar(); 8 if(c == ‘-‘)x = -x; 9 }10 inline int min(int a, int b){return a < b ? a : b;};11 12 const int INF = 0x3f3f3f3f;13 const int MAXN = 200 + 10;14 15 int dp[MAXN], n, h[MAXN];16 17 int ans = INF;18 int main()19 {20 read(n);21 for(int i = 1;i <= n;++ i)22 read(h[i]);23 memset(dp, 0x3f, sizeof(dp));24 dp[1] = 0;25 for(int i = 2;i <= n;i ++)26 {27 if(h[i] == h[i - 1] + 1)28 dp[i] = dp[i - 1] + 1;29 for(int j = 1;j < i;j ++)30 {31 int k = (int)log2(h[i] - h[j]);32 if((1 << k) + h[j] < h[i])k ++;33 if(j + k < i)34 dp[i] = min(dp[i], dp[j + k] + k + 1);35 }36 }37 if(dp[n] >= INF)38 printf("%d", dp[n]);39 else40 printf("-1"); 41 return 0;42 }
洛谷P1929 迷之阶梯
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。