蓝桥杯-秘密行动

本文探讨了在具有特殊跳跃能力的小D挑战大厦顶层任务中,如何利用动态规划求解最短时间路径。通过分析状态转移方程和初始化步骤,展示了如何计算从底层到顶层的最少时间。

秘密行动

资源限制

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

小D接到一项任务,要求他爬到一座 nnn 层大厦的顶端与神秘人物会面。这座大厦有一个神奇的特点,每层的高度都不一样,同时,小D也拥有一项特殊能力,可以一次向上跳跃一层或两层,但是这项能力无法连续使用。已知向上1高度消耗的时间为1,跳跃不消耗时间。由于事态紧急,小D想知道他最少需要多少时间到达顶层。

输入格式

第一行包含一个整数 nnn,代表楼的高度。

接下来n行每行一个整数 aiaiai,代表i层的楼层高度(aiaiai <= 100)。

输出格式

输出1行,包含一个整数,表示所需的最短时间。
样例输入

5
3
5
1
8
4

样例输出

1

数据规模和约定

对20%的数据,nnn<=10
对40%的数据,nnn<=100
对60%的数据,nnn<=5000
对100%的数据,nnn<=10000

题解

动态规划的经典题型。本题的题目稍微有些脱离现实,因为从生活角度来说,到达第一层应该不需要爬楼梯或跳跃,本题的意思接近于:到达第n层的楼顶所需要的最短时间。

对于到达每一层,都具有两个状态,一个是爬上来的,一个是跳跃上来的。

  • 如果第 iii 层是爬上来的,那么就是从第 i−1i-1i1 层爬上来的,至于如何到达的第 i−1i-1i1 层,无所谓,因为跳跃不能连续,但是爬楼梯可以连续。那么最短时间就是到达第 i−1i-1i1 层的最短时间+第 iii 层的高度。
  • 如果第 iii 层是跳上来的,那么就是从第 i−1i-1i1 层或第 i−2i-2i2 层跳上来的,但是到达第 i−1i-1i1 层或第 i−2i-2i2 层一定是爬楼梯上来的。最短时间就是爬楼梯上到第 i−1i-1i1 层或第 i−2i-2i2 层的最小值。

状态转移方程
dp[0][i]=min(dp[0][i−1]+height[i],dp[1][i−1]+height[i]dp[1][i]=min(dp[0][i−1],dp[0][i−2]) \begin{aligned} dp[0][i] &= min(dp[0][i-1]+height[i], dp[1][i-1] + height[i]\\ dp[1][i] &= min(dp[0][i-1],dp[0][i-2]) \end{aligned} dp[0][i]dp[1][i]=min(dp[0][i1]+height[i],dp[1][i1]+height[i]=min(dp[0][i1],dp[0][i2])
初始状态
dp[0][1]=height[1]dp[1][1]=0dp[0][2]=min(dp[1][1]+height[2],dp[0][1]+height[2])dp[1][2]=min(dp[0][1],dp[0][0]) \begin{aligned} dp[0][1] &= height[1]\\ dp[1][1] &= 0\\ dp[0][2] &= min(dp[1][1]+height[2], dp[0][1] + height[2])\\ dp[1][2] &= min(dp[0][1], dp[0][0]) \end{aligned} dp[0][1]dp[1][1]dp[0][2]dp[1][2]=height[1]=0=min(dp[1][1]+height[2],dp[0][1]+height[2])=min(dp[0][1],dp[0][0])
代码

n = int(input())
height = [0 for i in range(n+1)]
for i in range(1,n+1):
	height[i] = int(input())
if n <= 2:
	print(0)
else:	
	dp = [[0]*(n+1) for i in range(2)]
	# dp[0][x]表示到达第x层是爬着
	# dp[1][x]表示达到第x层是跳跃
	dp[0][1] = height[1]
	dp[1][1] = 0
	dp[0][2] = min(dp[1][1]+height[2], dp[0][1] + height[2])
	dp[1][2] = min(dp[0][1], dp[0][0])

	for i in range(2, n+1):
		dp[0][i] = min(dp[0][i-1]+height[i], dp[1][i-1] + height[i])
		dp[1][i] = min(dp[0][i-1],dp[0][i-2])
	print(min(dp[0][n], dp[1][n]))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值