动态规划算法学习(一)爬楼梯和凑金额
爬楼梯
每步可跨台阶:1,2,3 —该场景表示有序组合
台阶总数:15
求多少种跨法
'''
倒推下,当我倒数第二步已经走了14、13或12步时,我最后一步就可以就可以走完15个台阶此时我15步的走法跟最后一步无关,而是跟前面的三种结果有关,即是12+13+14步的走法和
由此再分别倒推14/13/12三种情况的走法,得到是13+12+11和12+11+10和11+10+9九种情况的走法和
....
在分解到最后,你就会发现是多个1/2/3走法的和
以F表示走法的函数,i表示台阶总数,F(i-1)、F(i-2)、F(i-3)分别表示最后一步为1/2/3的情况
即 F(i) = F(i-1)+F(i-2)+F(i-3)
我们建立一个数组,以下标表示总台阶数,则长度为n+1,再在每一个坐标元素上设置值为对应的总走法数
即有 [0,1,2,4,
'''
n = 15
steps = [1, 2, 3]
list_a = [0] * (n + 1)
list_a[0] = 1 # 总台阶数为0时0种走法,但是为了后面好进行迭代,我们设置为1,
list_a[1] = 1 # 总台阶数为1时只有[{1}]这一种走法,使用公式应为 f[0]的走法与最后一步为1的走法的组合
list_a[2] = 2 # 总台阶数为2时有[{1,1},{2}]这2种走法,使用公式应为 f[1]的走法与最后一步为1的走法的组合加上f[0]与最后一步为2的走法的组合
list_a[3] = 4 # [{1,1,1},{1,2},{2,1},{3}]
list_a[4] = 7 # [{1,1,1,1},{1,2,1},{2,1,1},{3,1}, {1,1,2}{2,2}, {1,3} ]
#上面是一个介绍过程,使用循环我们可以写成:
list_b = [0] * (n + 1)
list_b[0] = 1 # 初始化,方便计算,正常应该是0的
for i in range(1, n + 1): # 循环给每一总台阶为i时计算走法for s in steps: # 计算总台阶为i时最后一步为 s的走法if i >= s: # 必须总台阶数大于步数才有走法list_b[i] += list_b[i - s] # 总台阶数为 i时计算各个最后一步为s的走法的和
print(list_b[1])
print(list_b[2])
print(list_b[3])
print(list_b[4])
print(list_b[5])
print(list_b[6])
print(list_b[15])
C:\Python39\python.exe D:/PyWork/test_script/leetcode20220212.py
1
2
4
7
13
24
5768
凑金额
硬币面值:1,2,5 —这种场景与爬楼梯不一样,你在挑选时可以1,2,1或2,1,1的凑出4块钱,但是最后还是只算一种组合方式。
此时需要用背包算法来进行考虑
总金额:15
求组合方式
'''
背包算法就是指一堆指定面额/体积/重量的物品放入背包,求最大数量/方法/价值等内容的算法
如果物品每样只有一个就是0,1背包,方或者不放;不限制数量就是完全背包
这个场景就是不限制物品数量的场景
无序的话我们就不考虑取硬币的顺序而是考虑取硬币的数量。
我们可以用dp表(dynamic programming动态规划)表来进行推算总金额 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | # 下面的行往下一次表示只有1面额,有1和2面额,有1,25三种面额的情况1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | #这行表示在只有1这一种面值的情况下,此时只会有一种组合方式
面额 2 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 5 | #这行表示只有1和2两种面额时的场景5 | 1 | 1 | 2 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #这行表示有1,2,5三种面额的场景
金额为0时,没有组合方式
当我们只选择面值为1(i=0)的硬币时,不管总金额j>0为多少,只有一种组合方式,就是全部取面额为1的硬币,得到 dp[0][j]=1
当我们选择取面值为1/2两种硬币时,有不取2面额的取法,有取2面额的取法。当总金额每增加2,面额2就可以增加1,取法数也增加1
跟上面爬楼梯的思考方式类似,在同金额面值不同总金额的条件下发现也有F[i][j] = F[i][j-coins[i])+1的算法,
在不同面值同金额时就是F[i][j] = F[i-1][j]+j//coins[i]
我们可以先循环总金额(意思是以面额为外层,里面为金额,先循环完里面再循环一次外面),再循环面值
'''
coins = [1, 2, 5]
n = 15
dp = [[0] * (n + 1) for i in range(len(coins))] # 初始化dp表
for i in range(n + 1):dp[0][i] = 1 # 第一行只有一个面额硬币,组合始终是1
for j in range(len(coins)):dp[j][0] = 1 # 初始第1化列,为了方便迭代作为1
[print(i) for i in dp] # 可以看看初始化的dp表
for i in range(1, len(coins)): # 遍历币种,第一种全是1就跳过了for j in range(1, n + 1): # 先循环金额if j >= coins[i]: # 考虑1块钱时没有往前退两块到-1的场景。这个条件主要在i小于2和小于5时对对应的2/5面值生效dp[i][j] = dp[i][j - coins[i]] + dp[i - 1][j]# dp[i - 1][j]表示不取i币种时的取法,dp[i][j - coins[i]]表示取i币种时(你可以看最后的打印dp[2][8]和dp[2][3],8金额的取法就是在3金额的取法后面各加了一个5面值,取法数不变的)else: # 金额要大于币种才计算,1块钱时使用2块的面额用不了,此时只有1块的取法dp[i][j] = dp[i - 1][j]
print("========================完成计算后的dp表============")
[print(i) for i in dp]
print(dp[2][1]) # 1 [{1}]
print(dp[2][2]) # 2 [{1,1},{2}]
print(dp[2][3]) # 2 [{1,1,1},{1,2}]
print(dp[2][4]) # 3 [{1,1,1,1},{1,1,2},{2,2}]
print(dp[2][5]) # 4 [{1,1,1,1,1},{1,1,1,2},{1,2,2},{5}]
print(dp[2][6]) # 5 [{1,1,1,1,1,1},{1,1,1,1,2},{1,1,2,2},{2,2,2},{1,5}]
print(dp[2][7]) # 6 [{1,1,1,1,1,1,1},{1,1,1,1,1,2},{1,1,1,2,2},{1,2,2,2},{1,1,5},{2,5}]
print(dp[2][8]) # 7 [{1,1,1,1,1,1,1,1},{1,1,1,1,1,1,2},{1,1,1,1,2,2},{1,1,2,2,2},{2,2,2,2},{1,1,1,5},{1,2,5}]
print(dp[2][15])
C:\Python39\python.exe D:/PyWork/test_script/leetcode20220212.py
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
========================完成计算后的dp表============
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8]
[1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 10, 11, 13, 14, 16, 18]
1
2
2
3
4
5
6
7
18
动态规划算法学习(一)爬楼梯和凑金额相关推荐
- 算法:Climbing Stairs(爬楼梯) 6种解法
说明 算法:Climbing Stairs(爬楼梯) LeetCode地址:https://leetcode.com/problems/climbing-stairs/ 题目: You are cli ...
- 动态规划/滚动数组/通项公式——爬楼梯
一.题目 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 二.思路解析 1.迭代 第n个台阶只能从第n-1或者n-2个上来.到第 ...
- 动态规划——使用最小花费爬楼梯(Leetcode 746)
题目选自Leetcode 746.使用最小花费爬楼梯 题目描述: 解题代码:C语言 int minCostClimbingStairs(int* cost, int costSize) {int pr ...
- 程序设计与算法----递归之爬楼梯问题
爬楼梯 树老师爬楼梯,它可以每次走1级或者2级,输入楼梯的级数,求不同的走法数 例如:楼梯一共有3级,它可以每次都走一级,或者第一次走一级,第二次走两级,也可以第一次走两级,第二次走一级,一共有3种走 ...
- 一步一步写算法(之爬楼梯)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 前两天上网的时候看到一个特别有意思的题目,在这里和朋友们分享一下: 有一个人准备开始爬楼梯,假 ...
- LeetCode动态规划 使用最小花费爬楼梯
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始). 每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶 ...
- 神奇的口袋(动态规划)--算法学习
问题描述 有一个神奇的口袋,总的容积是40,用这个口袋可以变出 一些物品,这些物品的总体积必须是40. John现在有n(1≤n ≤ 20)个想要得到的物品,每个物品 的体积分别是a1,a2--a ...
- 动态规划算法学习二:最长公共子序列
文章目录 前言 一.问题描述 二.DP实现 1.最优子结构性质***** 2.状态表示***** 3.状态递归方程***** 4.计算最优值***** 5.代码实现:输出最长公共子序列 6.代码实现: ...
- 滑雪(动态规划)--算法学习
问题描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激. 可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底, 你不得不再次走上坡或者等待升降机来载你. Michael想知道载一个区 ...
最新文章
- 解决putty中文乱码并远程访问linux界面功能
- 用两张图告诉你,为什么你的App会卡顿?
- inputstreamreader未关闭会导致oom_Linux内核OOM机制分析和防止进程被OOM杀死的方法...
- asp.net处理机制管道事件
- Hive建表与数据加载
- 2007年IT技术走向何方 网络将再掀“酷”革命
- jQuery扩展半Lambda表达式 类似Linq的Where
- adminlte3 动态菜单_一本科学菜单,十倍利润增长 | 跟巴奴学餐饮业的精简风:菜单越薄,利润越厚!...
- Grub 开启serial console支持
- JAVA项目在服务器部署过程
- 和“目标”相关的名言
- ComposeOptions.kotlinCompilerVersion is deprecated
- 为什么选择高防DNS云解析?(二)
- win7截屏快捷键未在计算机上运行,修复win7“截图工具当前未在计算机上运行”的方法...
- 2011-12-24
- 数据库删改都不会,还能被录用:女程序员要求这么宽松?
- 一个疯子的梦-20190921
- mysql 去除微秒_mysql的微秒补丁 - sihanjishu的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
- 搜狗广告联盟不显示广告的原因
- python天气查询_python天气查询