《剑指offer》面试题88:爬楼梯最少的成本(python实现)

"""
题目:一个数组cost的所有数字都是整数,它的到底i个数字表示在一个楼梯的第i级台阶往上爬的成本,在支付了成本cost[i]后可以从第i级台阶
往上爬1级或者2级。假设台阶至少有2级,既可以从第0级台阶出发,也可以从第1级台阶出发,请计算爬上台阶的最少成本。
例如:输入数组[1,100,1,1,100,1],则爬上该楼梯的最少成本是4,分别经过下标为0、2、3、5的这4级台阶。

分析:
首先,动态规划题往往都出的是一个故事,比如偷东西、爬楼梯,这些我认为在思考问题时都应该摒弃掉,直接看问题的本质。
     如此题中,就应该看为给你一个数组,请计算数组内元素的和的最小值。要求元素的索引间隔不能超过2,可以从第0个或第1个元素开始计算。
其次,动态规划的关键是推导出元素索引之间的动态变化关系,然后使用递归进行推导,这里的递归往往会有很多次,因此必须使用备忘录。
     因此,我可以认为就是套公式:函数为dp,用于描述推导关系。此函数必然有三个参数:数组、备忘录,索引值。即dp(数组,备忘录,索引值)
然后,推导元素索引之间的动态变化关系,一般都是从结尾开始推导,即当索引值为最后一个元素时,并且假设它前面的结果都知道了,
     那么这最后一个元素的函数应该怎么写,由此即可推导出dp函数该怎么写。
最后,让我以此题为例,给定数组costs = [1,100,1,1,100,100],当站到最后一个元素costs[5]的位置上,要算站在这个位置上,它的最小值是多少。
     假设前面的位置的最小值都知道了,那么我们必然要选择dp(数组,备忘录,4)和dp(数组,备忘录,3)的最小值加上costs[5]作为这个位置上的最小值。
     即dp(数组,备忘录,5) = min( dp(数组,备忘录,4), dp(数组,备忘录,3) ) + costs[5].
     然后往前递归,当递归到第0个或者第1个元素时,就可以终止递归了。

另外:递归的返回,一定要用备忘录,如dp(数组,备忘录,3),在大于3的索引位置上,必然每个都会算,
     即dp(数组,备忘录,4)、dp(数组,备忘录,5)、dp(数组,备忘录,6)...都要算一次dp(数组,备忘录,3)的结果,这将是一个非常消耗资源的事情,
     因此一定要使用备忘录。备忘录用字典,字典的键为索引i,值为前面算出来的i个元素的dp函数值。
     当计算第i个元素的dp值时,先检查索引i是否在备忘录中,有的话直接返回它的值,没有的话再进行计算并放到备忘录里。


"""

def dp(costs,result_map,i):
    if i < 2:
        return costs[i]
    else:
        if i in result_map:
            return result_map[i]
        else:
            cost = min(dp(costs,result_map,i-1),dp(costs,result_map,i-2))+costs[i]
            result_map[i] = cost
            return cost
def up_satir(costs):
    result_map = {}
    length = len(costs)
    cost = min(dp(costs,result_map,length-1),dp(costs,result_map,length-2))
    print(cost)

costs = [1,100,1,1,100,100]
up_satir(costs)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值