【算法】动态规划
动态规划
原理
动态规划先解决子问题,再逐步解决大问题。但仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用
比较方法
可以使用表格法逐个罗列分析,每个表格中填写子问题最优解
示例
包容量为4磅,商品有三件,吉他($1500),音响($3000),电脑($2000),尽可能装下总和最贵的物品
解题思路
网格的各行为商品,各列为不同容量(1~4磅)的背包。所有这些列你都需要,因为它们将
帮助你计算子背包的价值。
|
1磅 |
2磅 |
3磅 |
4磅 |
吉他(G) |
$1500 |
$1500 G |
$1500 G |
$1500 G |
音响(S) |
$1500 |
$1500 |
$1500 |
$3000 |
电脑(L) |
$1500 |
$1500 |
$2000 |
$3500 |
公式
cell[i][j]=以下两者中较大的那个
- 上一个单元格的值(即cel[i-1][j]的值)
- 当前商品的价值+剩余空间的价值(剩余空间的价值: cell[i-1][j-当前商品的重量])
表格中的行或者列位置变换,不会影响最终结果
动态规划启示
- 动态规划可帮助在给定约束条件下找到最优解
- 在问题可分解为彼此独立且离散的子问题时,就可使用动态规划来解决。
- 每种动态规划解决方案都涉及网格。
- 单元格中的值通常就是你要优化的值。
- 每个单元格都是一个子问题,因此你应考虑如何将问题分成子问题,这有助于找出网格的坐标轴
最长公共子串
费曼算法( Feynman algorithm)。
步骤
(1) 将问题写下来。
(2) 好好思考。
(3) 将答案写下来。
此处为抖机灵(ˉ▽ ̄~) ~~
示例
对比hish与fish或vista哪个的公共子串更长?
- hish和fish
|
H |
I |
S |
H |
F |
O |
O |
O |
O |
I |
O |
1 |
O |
O |
S |
O |
O |
2 |
O |
H |
O |
O |
O |
3 |
- hish和vista
|
V |
I |
S |
T |
A |
H |
O |
O |
O |
O |
O |
I |
O |
1 |
O |
O |
O |
S |
O |
O |
2 |
O |
O |
H |
O |
O |
O |
O |
O |
PS: 最终答案并不在最后一个单元格.对于最长公共子串问题,答案为网格中最大的数字
计算方法
- 如果两个字母不同,值为O
- 如果两个字母相同,值为左上角邻居的值加1
伪代码实现
if word_a[i]==word_b[j]: cell[i][j]=cell[i-1][j-1]+1 else: cell[i][j]=0
最长公共子序列
定义
最长公共子序列:两个单词中都有的序列包含的字母数
示例
fosh,对比fish、fort?
最长公共子串方法
- fosh vs fort
|
F |
O |
S |
H |
F |
1 |
O |
O |
O |
O |
O |
2 |
O |
O |
R |
O |
O |
O |
O |
T |
O |
O |
O |
O |
- fosh vs fish
|
F |
O |
S |
H |
F |
1 |
O |
O |
O |
I |
O |
O |
O |
O |
S |
O |
O |
1 |
O |
H |
O |
O |
O |
2 |
结果相同均为2
最长公共子序列方法
- fosh vs fort
|
F |
O |
S |
H |
F |
1 |
1 |
1 |
1 |
O |
1 |
2 |
2 |
2 |
R |
1 |
2 |
2 |
2 |
T |
1 |
2 |
2 |
2 |
- fosh vs fish
|
F |
O |
S |
H |
F |
1 |
1 |
1 |
1 |
I |
1 |
1 |
1 |
1 |
S |
1 |
1 |
2 |
2 |
H |
1 |
1 |
2 |
3 |
计算方法
- 如果两个字母不同,就选择上方和左方邻居中较大的那个
- 如果两个字母相同,就将当前单元格的值设置为左上方单元格的值加1
伪代码实现
if word_a[i]==word_b[j]: cell[i][j]=cell[i-1][j-1]+1 else: cell[i][j]=max(cell[i-1][j],cell[i][j-1])
小结
- 需要在给定约束条件下优化某种指标时,动态规划很有用。
- 问题可分解为离散子问题时,可使用动态规划来解决。
- 每种动态规划解决方案都涉及网格。
- 单元格中的值通常就是你要优化的值。
- 每个单元格都是一个子问题,因此需要考虑如何将问题分解为子问题
- 没有放之四海皆准的计算动态规划解决方案的公式。