问题描述
小D接到一项任务,要求他爬到一座n层大厦的顶端与神秘人物会面。这座大厦有一个神奇的特点,每层的高度都不一样,同时,小D也拥有一项特殊能力,可以一次向上跳跃一层或两层,但是这项能力无法连续使用。已知向上1高度消耗的时间为1,跳跃不消耗时间。由于事态紧急,小D想知道他最少需要多少时间到达顶层。
输入格式
第一行包含一个整数n,代表楼的高度。
接下来n行每行一个整数ai,代表i层的楼层高度(ai <= 100)。输出格式
输出1行,包含一个整数,表示所需的最短时间。
样例输入
5
3
5
1
8
4样例输出
1
老样子,话不多说先上代码。
#include <stdio.h>
#include <stdlib.h>
int min2(int x,int y);
int main()
{
int n,i=0,j=0;
scanf("%d",&n);
int hi[n+1];
int dp[2][n+1];
hi[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&hi[i]);
}
for(i=0;i<2;i++)
{
for(j=0;j<=n;j++)
{
dp[i][j]=0;
}
}
dp[0][1]=hi[1];
dp[1][1]=0;
for(i=2;i<=n;i++)
{
dp[0][i]=min2(dp[0][i-1]+hi[i],dp[1][i-1]+hi[i]);
dp[1][i]=min2(dp[0][i-1],dp[0][i-2]);
}
int time;
time=min2(dp[0][n],dp[1][n]);
printf("%d",time);
return 0;
}
int min2(int x,int y)
{
int t;
if(x<=y){t=x;}
if(y<=x){t=y;}
return t;
}
分析题目:
输入一个楼层数,然后输入各层高度,最后输出我们的最短时间。
题目已经很明确的给定了一个一维数组,即我们的各个楼层的高度,而我们上每一层都有两个状态,要么是爬,要么是跳,那么很明显我们设置的动态dp数组需要是二维数组,0这一行我们用来表示爬的状态,1这一行我们用来表示跳的状态。
数组元素的意义为我们爬到 i 层或跳到 i 层所花费的时间,到这里我们的数组状态就设计好了,接下来就是状态转移方程。
对于状态转移方程,我们只需要安装题目给定的解题步奏做就行了,对于这道题的解题思路应该是这样的:
1:首先我们到达第 i 层只有跳和爬两个方法,而跳跃是不能连续的,所以说我们爬到第 i 层那么第 i-1 层我们必定是爬上来的或者跳上来的,而我们要求时间最短所以说需要取最小(取最小用min代替),而不管怎么说我们这一层都要爬所以说付出的时间都需要加上对应这一层的所需要花费的时间,所以说爬到第 i 层的状态转移方程为:
dp[0][i]=min(dp[0][i-1]+hi[i] , dp[1][i-1]+hi[i]);
2:我们要是像要跳到第 i 层也有两个状态,但是前提是我们如果从i-1跳到 i 层那么 i-1 的前一层
i-2我们必须是爬的,而我们一次最多跳两层,所以我们可以从i-1或者i-2层起跳,那么对应的其前一层我们必须是爬的,而我们跳跃不花费时间,所以我们到达第i层的的代价就是其对应的上一层爬的时间,那么状态转移方程就应该为:
dp[1][i]=min(dp[0][i-1],dp[0][i-2]);
这里有点绕,其实就是因为我们从i-1跳到i层是不需要花费时间的,那么我们跳跃到这一层花费的时间是不是我们到达i-1层的时间,而因为我们跳跃的前一次必定是爬行那么我们所花费的时间直接从dp数组代表爬操作的这一行取就行了。
到这里状态转移方程我们也设计完了,接下来是设计程序
设计程序:
设计程序时,我们需要注意初始状态,即我们抵达第一层时跳跃和爬所花费的时间,除此之外没有其他的初始状态,而我们给定了初始状态,只需要规划后面的几步,所以循环我们需要从第二层开始计算。