题目 2250: 蓝桥杯算法提高-秘密行动

题目

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

输入
第一行包含一个整数n,代表楼的高度。
接下来n行每行一个整数ai,代表i层的楼层高度(ai <= 100)。

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

样例输入

5
3
5
1
8
4

样例输出

1

解题思路

本题可以用深度优先的搜索,但是可能会超时,更优的方法是使用动态规划。首先分析可以得到如下表格,表格中记录的数值是到当前层所需的最短时间(数据来自于样例):

层数爬到到第i层(j=0)跳跃到第i层(j=1)
000
130
250
313
491
551
nmin(dp[n-1][0],dp[n-1][1])+a[n]min(dp[n-1][0],dp[n-2][0])

表格的"j=0"列,表示的是从上一次落脚的层,即第(i-1)层,是通过爬的方式到达当前层(第i层)的;"j=1"列,则代表小D是通过跳跃的方式,从上一次落脚的层,即(i-1)或者(i-2)层,到达第i层的。

因此,如果小D要前往第i层,如果选择爬,则上一步可以是跳跃,也可以是爬,那么之前的路线则选择耗时最短的,即总时间有min(dp[i-1][0],dp[i-1][1])+a[n](这里存在为什么向上爬都爬一层的问题,是因为题目要求耗时最短的,那么肯定减少爬的楼层数目);如果选择跳跃,那么上一步必然要是爬,且跳跃高度为1或2层,所以小D当前所处的楼层必然是(i-1)或者(i-2),因此,有min(dp[i-1][0],dp[i-2][0])。将以上描述写为状态转移方程,有:
{ d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] ) + a [ n ] d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 0 ] , d p [ i − 2 ] [ 0 ] ) \left\{ \begin{aligned} &dp[i][0]= min(dp[i-1][0],dp[i-1][1])+a[n]\\ &dp[i][1]= min(dp[i-1][0],dp[i-2][0])\\ \end{aligned} \right. {dp[i][0]=min(dp[i1][0],dp[i1][1])+a[n]dp[i][1]=min(dp[i1][0],dp[i2][0])
最终答案是min(dp[n][0],dp[n][1])。

代码

#include<stdio.h>

int min(int a, int b){
    return (a>b)?b:a;
}

int main()
{
	int n,i;//n表示楼层数
	scanf("%d",&n);
	int a[n+1],dp[n][2];
	for (i=1;i<=n;i++)
	    scanf("%d",&a[i]);
	
	dp[0][0]=0,dp[0][1]=0;
	dp[1][0]=a[1],dp[1][1]=0;
	for (i=2;i<=n;i++)
	{
	    dp[i][0] = min(dp[i-1][0],dp[i-1][1])+a[i];
	    dp[i][1] = min(dp[i-1][0],dp[i-2][0]);
	}
	if (n>0 && n<=2)
	    printf("1");
    else
	    printf("%d",min(dp[n][0],dp[n][1]));
	return 0;
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值