蓝桥云课——路径 Python(动态规划)

 题目地址:路径

        动态规划第一步:,确认dp数组含义,题目中提到“ 结点 1 和结点 2021 之间的最短路径长度是多少。”,所以我们dp数组的含义便是最短路径。

        动态规划第二步,确认dp数组。由题意得,在第i和第i+21两个点之间有一条无向边,而再往后延伸例如i+23因为差值大于21以至于没有边,但是我们发现i+21与i+23之间的差值是小于21的,这时候i到i+23两点的距离便可以表示为:i到i+21之间的距离 + (i+21)到(i+23)的边长度,若是再加上求最短路径:我们便可以表示为(i到i+21之间的最短路径 + (i+21)到(i+23)的边长度),对于题目求结点1-结点2021最短路径长度便拆分为:求结点1-结点2020之间的最短路径 + 结点2020到结点2021的边长度,对此我们可以再次拆分,因为大于21后边没有了无向边,所以我们可以拆为min[(结点1到结点2000之间的最短路径 + 结点2000到结点2021的边长度),(结点1到结点2009之间的最短路径 + 结点2009到结点2021的边长度),,,,(结点1到结点2020 + 结点2020到结点2021的边长度)],而对于1-2000之间的最短路径我们又可以再拆分......,最终我们可以拆到结点1到结点1之间的最短路径,所以我们从结点1从前往后推,21个数字为一组,所以我们从1-22之间的最短路径开始求,1-22最短路径=min[(结点1到结点2之间的最短路径 + 结点2到结点22的边长度),,,],所以我们dp数组边可以表示为最短路径 = min(最短路径, 另一条最短路径 + 边长度),即:dp[i] = min(dp[i], dp[j] + 最小公倍数)

        动态规划第三步,初始化dp数组,因为我们要找最短的,我们先把dp数组全设为最大:

dp = [float('inf')] * 2022

  因为结点1到结点1为0,所以把第一项的距离设为0:

dp[1] = 0

        对于最小公倍数,我们有计算公式:最小公倍数 = 两数乘积/两数之间最大公约数,而最大公约数Python库内有gcd函数:

import math

def func(x, y):
    return (x * y)//math.gcd(x, y)

 最后用两层for循环进行遍历:

for i in range(1, 2022):
    for j in range(i + 1,i + 22):
        if j > 2021:
            break
        dp[j] = min(dp[j], dp[i] + func(i, j))

完整代码:

import math
# 最短路径 = min(最短路径, 另一条最短路径 + 边长度)
dp = [float('inf')] * 2022
dp[1] = 0  # 1到1的最短路径为0

def func(x, y):
    return (x * y)//math.gcd(x, y)

for i in range(1, 2022):
    for j in range(i + 1,i + 22):
        if j > 2021:
            break
        dp[j] = min(dp[j], dp[i] + func(i, j))

print(dp[2021])

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值