【数据结构与算法】常用十大算法:动态规划
基本介绍
- 动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。
- 动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
- 我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。
分类
动态规划一般可分为线性动规,区域动规,树形动规,背包动规四类。
线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
区域动规:石子合并, 加分二叉树,统计单词个数,炮兵布阵等;
树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;
背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶等。
应用实例:
最短路径问题 ,项目管理,网络流优化……
实践:背包问题
问题描述
有一个背包,容量为 4 磅,现有如下物品:
物品 | 重量 | 价格 |
---|---|---|
吉他(G) | 1 | 1500 |
音响(S) | 4 | 3000 |
电脑(L) | 3 | 2000 |
- 要求装入背包的总价值最大,且重量不超出背包容量
- 装入物品不能重复(01背包)
思路分析
如基本介绍所说,我们不妨先列表寻找规律
物品 0磅 1磅 2磅 3磅 4磅 0 0 0 0 0 吉他(G) 0 1500(G) 1500(G) 1500(G) 1500(G) 音箱(S) 0 1500(G) 1500(G) 1500(G) 3000(S) 电脑(L) 0 1500(G) 1500(G) 2000(L) 2000(L)+ 1500(G) 设
weight[i]
、value[i]
分别表示第 i 个物品的重量和价值,total[i][j]
表示前 i 个物品中能够装入容量为 j 的背包中的物品的的最大价值每遍历一个物品,我们可以根据
weight[i]
、value[i]
计算是否需要把他放入背包中(能够放入的前提下放入会使背包中物品的总价值增加就放入)由图表易知:
当
weight[i] > j
(当装入物品质量大于背包容量时,直接使用上一单元格的策略)total[i][j] = total[i - 1][j]
当
weight[i] <= j
(当装入物品质量小于背包容量时,表示可以装进去)total[i][j] = Max{ total[i - 1][j] , value[i] + total[i - 1][j - weight[i]]}
total[i - 1][j]
:上一单元格装入的最大值value[i] + total[i - 1][j - weight[i]]
:装入前 i -1 商品到剩余空间j - weight[i]
的最大值
代码实现
其实整个代码实现过程就是依据上面分析的思路来还原整个图表!
1 | package com.atguigu.dynamic; |
输出结果:
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.