[Leetcode 120] Dynamic Programming - Triangle(三角形最小路径和)

这个题是维特比算法的一个典型应用,为了求全局最短路径,必须知道从初始位置到当前各位置的最短路径,再从当前位置,依次找到到达下一位置的最短路径。

为什么通过找到从初始位置到当前可到达位置的局部最优路径最终就能得到全局最优路径呢?设这条路径需要经过t个点,每个点的权重不相同,最后找到了一条路径,这条路径上的t个点的权值之和最小。令这条路径上的第i个点( 0 < i < t 0 < i < t 0<i<t)的位置为 l i l_{i} li,这个点将整条路径分为两部分: l 0 , ⋯   , l i l_{0},\cdots,l_{i} l0,,li l i + 1 , ⋯   , l t l_{i+1},\cdots,l_{t} li+1,,lt。那么如果我们假设 l 0 , ⋯   , l i l_{0},\cdots,l_{i} l0,,li这条路径不是从位置0到位置i的权值最小路径,就必然存在另一条从位置0到位置i的权值最小路径,这样就说明从位置0到位置t的最小权值还可以更小,这和我们的假设是矛盾的,由此可证, l 0 , ⋯   , l i l_{0},\cdots,l_{i} l0,,li这条路径必须是从位置0到位置i的局部最优路径。

import numpy as np

class Solution(object):
    def minimumTotal(self, triangle):
        """
        :type triangle: List[List[int]]
        :rtype: int
        """
        
        if len(triangle) == 0:
            return 0
        
        viterbi = [-1] * len(triangle)
        
        for index, elements in enumerate(triangle):
            # print('elements--', elements)
            if index == 0:  # 如果是第一行,直接给第一个值赋值
                viterbi[0] = elements[0]
            else: #如果不是第一行,则根据当前的局部最短路径分别寻找到达当前位置的最短路径
                
                tmp_viterbi = np.copy(viterbi)
                # print('tmp_viterbi---', tmp_viterbi)
                for i, element in enumerate(elements):
                    if i == 0:  # 每一行的0元素位置只能从上一行的0元素位置处过来
                        viterbi[i] = tmp_viterbi[i] + element
                        print('tmp_viterbi[{}]={}, element={}'.format(i, tmp_viterbi[i], element))
                        continue
                    
                    if i == len(elements) - 1:  # 当前行的最后一个元素只能从上一行的最后一个位置处到达
                        viterbi[i] = tmp_viterbi[i-1] + element
                        # print('tmp_viterbi---', tmp_viterbi)
                        continue
                        
                    # 0 < i < len(element) - 1
                    viterbi[i] = min(tmp_viterbi[i-1], tmp_viterbi[i]) + element
                    # print('tmp_viterbi---', tmp_viterbi)

            # print(viterbi)
                
            # 如果已经到了最后一行,则找出其中最小的值返回即可    
            if index == len(triangle) - 1: 
                return min(viterbi)
          


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值