栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

动态规划- python及递归

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动态规划- python及递归

文章目录
  • 零钱兑换问题---动态规划解法
    • 采用动态规划来解决11分钱的兑换问题
    • 动态规划扩展算法
    • LeetCode 322. 零钱兑换


零钱兑换问题—动态规划解法

递归算法https://blog.csdn.net/suwuzs/article/details/121666346
在递归优化的过程中,我们用了中间结果记录的方法。这种方法叫做memoization(记忆化/函数值缓存)技术,可以提高递归解法的性能。

  • 零钱兑换的动态规划算法是从最简单的‘1分钱’找零的最优解开始,逐步递加上去,直到我们需要的找零钱数;
  • 在找零递加的过程中,设法保持每一分钱的递加都是最优解,一直加到求解找零钱数,自然得到最优解。

递加的过程能保持最优解的关键是,依赖于更少钱数最优解的简单计算,而更少钱数的最优解已经得到了了。

问题最优解包含了更小规模子问题的最优解,这是一个最优化问题能够用动态规划策略解决的必要条件。

numCoins = min(
    1 + numCoins(original - 1),
    1 + numCoins(original - 5),
    1 + numCoins(original - 10),
    1 + numCoins(original - 25),
)
采用动态规划来解决11分钱的兑换问题

从1分钱开始兑换,逐步建立一个兑换表;

兑换1234567891011
个数1
12
123
12341
省略
1234123451
12341234512

计算11分钱的兑换法,我们氛围以下几步:

  • 首先减去1分钱,剩下10分钱,查表最优解是1;(1+1)
  • 然后减去5分钱,剩下6分钱,查表最优解是2;(1+2)
  • 最后减去10分钱,剩下1分钱,查表最优解是1。(1+1)

通过上述过程,得到的最小值,最优解是2。

def dp_change(coinList, change, minCoins):
    for cent in range(1,change+1):
        coinCount = cent
        for i in [c for c in coinList if c <= cent]:
            if minCoins[cent-i] + 1 < coinCount:
                coinCount = minCoins[cent - i] + 1
        minCoins[cent] = coinCount

    return minCoins[change]
ls = [1,5,10,21,25]
print(dp_change(ls,63,[0]*64))
  • 动态规划算法并不是递归函数;
  • 动态规划的主要思想;
    从最简单情况开始到达所需找零的循环,其每一步都依靠以前的最优解来得到本步骤的最优解,直到得到答案。
动态规划扩展算法

返回硬币的组合;

只需要在生成最优解列表同时跟踪记录所选择的那个硬币币值即可。

在得到最后的解后,减去选择的硬币币值,回溯到表格之前的部分找零,就能逐步得到每一步所选择的硬币币值。

def dp_change(coinList, change, minCoins, coinUsed):
    for cent in range(1,change+1):
        coinCount = cent
        newCoin = 1 #初始化新加硬币
        for i in [c for c in coinList if c <= cent]:
            if minCoins[cent-i] + 1 < coinCount:
                coinCount = minCoins[cent - i] + 1
                newCoin = i #对应最小数量,所减的硬币
        minCoins[cent] = coinCount
        coinUsed[cent] = newCoin #记录本次步骤所加的1个硬币
    return minCoins[change]
    
def printCoins(coinUsed,change):
    coin = change
    while coin > 0:
        thisCoin = coinUsed[coin]
        print(thisCoin)
        coin = coin - thisCoin
ls = [1,5,10,21,25]
amt = 63
coinUsed = [0]*(amt+1)
print(dp_change(ls,amt,[0]*(amt+1),coinUsed))
print('-------')
printCoins(coinUsed,amt)
输出:
3
-------
21
21
21
LeetCode 322. 零钱兑换

def dp_change(coinList, change):
    minCoins = [float('inf')] * (change+1)
    minCoins[0] = 0
    for coin in coinList:
        for x in range(coin, change+1):
            minCoins[x] = min(minCoins[x], minCoins[x-coin] + 1)
        
    return minCoins[change] if minCoins[change] != float('inf') else -1

ls = [1, 5, 10, 21, 25]
print(dp_change(ls, 63))
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/630349.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号