这篇文章跟上篇文章都是leetcode中的简单题,对于大佬来说可能非常简单,但是对于新手来说还是可以做一做的,理解动态规划的步骤就得从简单的开始,话不多说,接下来就由小仙来讲一讲我的理解及感受。
题目:
实例:
符号假设:
cost[i]:从第i级阶梯跨越的花费
dp[i]:跨过第i级阶梯所需要的最小花费
问题分析:
题目说的是到达第i级阶梯且跨过它的最小花费,且跨度是2,这里能够分析出两个关键点。
在进行跨越的时候,你可以选择跨1级,也可以选择跨2级,应题目要求,就选相对较小的跨;
与此同时,因为最大跨越度为2,所以这里肯定需要考虑到最后两个阶梯,有可能到第i-1级阶梯,此时直接跨越两步,直接到达顶峰,也有可能到第i级阶梯,再跨越一步到达顶峰。
状态分析:
假设子问题:跨过第i级阶梯的最小花费为dp[i]。
dp[i]与dp[i-1],dp[i-2],cost[i],cost[i-1]的关系分析。
假设此时到达了第i-1级阶梯,那么就可以直接跨越两步直接到达顶峰,此时的最小花费为,到达i-1级阶梯的最小花费加上跨越第i-1级阶梯的花费,所以有:dp[i-2] + cost[i-1] 。
假设此时到达了第i级阶梯,那么就直接跨越到达顶峰,此时的最小花费为,到达第i级阶梯的最小花费加上跨越第i级阶梯的花费,所以有:dp[i-1] + cost[i]。
那么到达顶峰的最小花费其实就是这两种情况的其中较小的一个情况min(dp[i-2] + cost[i-1] ,dp[i-1] + cost[i])
状态转移方程:
dp[i] = min(dp[i-2] + cost[i-1] ,dp[i-1] + cost[i])
初始状态:
这里需要注意题目中的最后一句,我们可以从下标为第0级或第1级出发,所以有dp[0] = 0,
dp[1] = min(cost[0],cost[1])
这里为了理解,举了个例子:
在动态规划分析中千万不要琢磨中间的每一个过程,只要找到状态情况和状态转移方程就可直接根据数学方程进行解答,否则会想懵,如果还是不理解的话,最好 可以举一个例子,如: [1,100,1,1,1,100,1,1,100,1] 这里设起点为-1,到达0阶梯的花费为0,那么可以如下进行假设: 子问题0:通过第0阶梯的最小花费 子问题1:通过第1阶梯的最小花费 子问题2:通过第2阶梯的最小花费 子问题3:通过第3阶梯的最小花费 子问题4:通过第4阶梯的最小花费 子问题5:通过第5阶梯的最小花费 ...... 子问题8:通过第8阶梯的最小花费 子问题9:通过第9阶梯的最小花费 最后:从子问题9跨两步直接到达A,或者从子问题10跨一步到达A [1,100,1,1,1,100,1,1,100,1] 解析式: 到达第i-1阶梯的最小花费 到达第i阶梯的最小花费 dp[-1] = 0 dp[0] = 1 dp[1] = min(dp[-1] + cost[0], dp[0] + cost[1]) = dp[-1] + cost[0] = 1 1 101 dp[2] = min(dp[0] + cost[1], dp[1] + cost[2]) = dp[1] + cost[2] = 2 101 2 dp[3] = min(dp[1] + cost[2], dp[2] + cost[3]) = dp[1] + cost[2] = 2 2 3 dp[4] = min(dp[2] + cost[3], dp[3] + cost[4]) = 3 3 3 dp[5] = min(dp[3] + cost[4], dp[4] + cost[5]) = dp[3] + cost[4] = 3 3 103 dp[6] = min(dp[4] + cost[5], dp[5] + cost[6]) = dp[5] + cost[6] = 4 103 4 dp[7] = min(dp[5] + cost[6], dp[6] + cost[7]) = dp[5] + cost[6] = 4 4 5 dp[8] = min(dp[6] + cost[7], dp[7] + cost[8]) = dp[6] + cost[7] = 5 5 104 dp[9] = min(dp[7] + cost[8], dp[8] + cost[9]) = dp[8] + cost[9] = 6 104 6
其实仔细观察会发现,因为跨越两步这个事件,在跨越的时候操作空间很大,有很多东西都被重复利用,注意这里并不是重复查询每一个子问题,而是直接利用,且相互利用的子问题之间的间隔很短。
代码:
def func0(): cost = list(map(int,input().split())) dp = [0] * len(cost) dp[0] = 0 dp[1] = min(cost[0],cost[1]) for i in range(2,len(cost)): dp[i] = min(dp[i-2] + cost[i-1],dp[i-1] + cost[i]) return dp[-1]
这个代码其实在空间上还可以优化一下,就是dp这个列表的操作,大家有兴趣可以试一下,这次就不放代码了(其实我也没敲,嘿嘿)。
这一期就这样了,大概最近这一个月都是发一些有关基础算法的文章,有兴趣的小伙伴可以一起学习。