动态规划 深度 理解

前言:
动态规划一定是记录状态的!
就是说你分析过程中可能会多次用到某些状态的信息,
那么动态规划是花一定空间去记录好这些 状态,避免每次用到时 都需要多次去计算相关信息。

常见情况比如:
一维的字符串,
可以建立一个二维的动态规划空间,
记录相关的信息。

动态规划的三个关键点:

名词定义:
**扩展临界点:**结构k 扩展到 结构k+1 时候,通过增加值value[i][j] (也有可能是value[i]或者value[j] ) ,结构k的问题区域 变成 结构k+1 的问题区域 。我们把
value[i][j] 或者 value[i]或者value[j] 称为 扩展临界点。

要能够清晰的分辨两个 主体 A B
或者多个主体,但一般是 A+C 统一考虑,等同于B
要能通过 准确分辨 原子结构,(如字符串的每个字符都是原子结构)
准确定义 不完全结构 (如字符串中的一部分 字串)

初始条件
状态转移方程(dp[i+1][j+1]
大多数情况都是与dp[i][j]建立联系,
其次是dp[i+1][j]和dp[i][j+1])
还有可能是 dp[xx][j],其中xx=0,1,2,3,4,5,6…
也还有可能是 dp[i][jxx],其中xx=0,1,2,3,4,5,6…

有时候要求 dp[i+1][j+1] ,但是情况很麻烦,可能最优值 包含 扩展 临界点,也有可能 不包含 扩展临界点。 这时候 我们可以尝试 强制包含 扩展临界点,然后求最优解, 而每次扩展的 最优解 从 之前的 所有的 最优解 中 找最好的就行。
难一点,就是 每次扩展的 最优解 从 之前的 所有的 满足一定条件的 最优解 中 找最好的 就行,
也就是 二次 寻最优

本质上,最优值 包含 扩展 临界点,也有可能 不包含 扩展临界点 的情况 无非就是 要么包含,要么不包含两种情况.
那么就求出包含的(其实求包含情况时,经常也需要 借助 之前的 子结构 最优解),
然后不包含的 其实就是 子结构 的最优解。
那么求子结构的 最优解的时候 同样可以 分解为 包含不包含,一直分解到第一种情况,其实整个过程 就是 求 每一次扩展时 都包含临界点,然后每次 求最优解 的时候,从前面 所有的 最优解中 二次寻最优 而已。

**核爆炸:状态转移方程可能的情况:
**

状态转移方程1:

F [ i ] = max { F [ j ] + 1 ,F [ i ] } (1 <= j < i,A[ j ] < A[ i ])
(最长上升子序列问题)
https://blog.csdn.net/lxt_Lucia/article/details/81206439?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

状态转移方程2:

dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + (A[i]==B[j] ? 1 : 0)),
(最长公共子序列 问题)
https://blog.csdn.net/lxt_lucia/article/details/81209962

此题的切入点就是动态规划,通过动归来确定哪些字符是最长公共子序列中的字符,mat[i][j] 表示第一个序列的前i个字符和第二个序列的前j个字符的公共子序列,动态转移方程为:

dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + (A[i]==B[j] ? 1 : 0)),表示在这三种状态中取到最大值,

(1)第一种状态表示不录入第一个序列的第i个字符时的最长公共子序列,

(2)第二种状态表示不录入第二个序列的第j个字符时的最长公共子序列,

(3)第三种状态表示第一个序列的前i-1个字符与第二个序列前j-1个字符的公共子序列加上最后一个字符的录入状态,如果最后的一个字符相等则录入状态为1,否则为0。

状态转移方程3:

product(p,q)=max{product(x,q-1)*number(x+1,p)}
(1<=x<=p-1)
(最大k乘问题)
https://blog.csdn.net/Azkkkkk/article/details/88851067
令number(i,j)表示第i位到第j位整数组成的(j-i+1)位整数;
令product(p,q)表示前p位整数被划分为q段所得到的最大乘积;
[若划分段数大于整数位数,则结果为0]

初始子问题:(q=1时)
product(p,1)=number(1,p)
无论多少位整数,被划分为一段,其最大k乘积均为其本身。
下一阶段子问题:(q>1且q<=p时)
product(p,q)=max{product(x,q-1)*number(x+1,p)}
(1<=x<=p-1)
p为整数分为q段,分别求出前x位这个数分为q-1段所得最大乘积与余下数段的乘积,选择合适的数据结构记录,然后进行比较,最大的结果即为product(p,q)。

状态转移方程4:

grid[i][j] += min(grid[i - 1][j], grid[i][j - 1]);
(矩阵最小路径问题)
https://blog.csdn.net/hang404/article/details/85279268
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。每次只能向下或者向右移动一步。

每个位置存储到达当前位置(i, j)的最小路径和,(i - 1, j)和(i, j - 1)都可到达该位置,所以位置(i, j)的路径和等于(i - 1, j)和(i, j - 1)中较小路径和与当前位置数值的和。

核爆:每次只能从(i - 1, j)或者(i, j - 1) 到达(i,j) 因此(i,j)的最大值只能是 这其中之一 加上当前点的值
所以不用考虑那一整行或者一整列。因为最大以(i - 1, j) 为 一个顶点的矩形 就 足以 能够包含 之前的任何一个。 (i, j - 1) 也一样。

状态转移方程5:
if (s1.charAt(i-1) == s2.charAt(j-1))
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = min(
dp[i - 1][j] + 1,
dp[i][j - 1] + 1,
dp[i-1][j-1] + 1
);
(编辑距离问题)
一个字符串通过 删除,增加,替换 一些字母,使得这个字符串变成 另一个字符串。
https://zhuanlan.zhihu.com/p/80682302

状态转移方程6:

状态转移方程7:

状态转移方程8:

难点,注意点:
有时候 dp[i+1][j+1] 的最优区域可能 包含value[i+1][j+1] 这个值,也可能不包含value[i+1][j+1]这个值。
但是如果前面就是 多原子扩展增量(看后面名词解释) 这种情况的话,情况可能会很复杂,这时候 我们可以 先 假设 dp[i+1][j+1] 的最优区域 包含value[i+1][j+1] 这个值,然后 在 dp[xx][j+1] (其中xx=0,1,2,3…)中或者dp[i+1] [xx] (其中xx=0,1,2,3…)找 中找最优值,即可作为 dp[i+1][j+1]的最优值。
其实也可以 这么理解 ,就是 有时候 dp[i+1][j+1] 的最优区域可能 包含value[i+1][j+1] 这个值,也可能不包含value[i+1][j+1]这个值 的这种情况,他无非就是 1包含,2不包含 这两种情况。 显然不包含的 肯定 存在于 前面 求出的 dp[i+1][j+1] 之前的那些值中。 现在直接 求出包含 的情况 ,然后 在 包含和不包含 之中遍历一次,找到 最优 的那个解 就行。

所以遇到 任何情况,比如可能包含很多可能的情况,一定不能感觉一团糟,
只需要 转换一下思想,以某个点(数据)为 零界点,
那么问题就会变成包含这点 和 不包含 这点 这两种情况了。

然后包含的就很好求。不包含的 其实 就是可以分解为 之前的 情况里最好的 一种,然后如此循环,每一种不包含的 其实都是 可以在之前的 中找到。 那么 就可以 从第一种 ,顺次 求出来。

同时,dp[i+1][j+1] 可能包含,可能不包含 l扩展临界点 value[i][j] (扩展临界点也有可能是value[i]或者value[j]) 的情况,其实 等同于 每一种 子情况 都包含 当前 临界点的情况中 找最优。

边界条件

两个基本要素
1.子问题重叠性
2最优子结构性质。

我的深度理解:

动态规划,一般都是找到一个 初始结构,
然后每次扩展一个结构。

很多问题的核心在于 如何扩展结构。
这里假设问题域为 字符串123456


首先提到 两个 我定义的名词: 原子结构
扩展增量
**** 单原子扩展增量 多原子扩展增量****

**原子结构是 x:也就是问题区域的极小组成单元是x,比如123456这里 任意单个 数字都可以是 原子结构,比如0, 1 2 3 4…6
扩展增量: 就是当前最优结构k 与下一个 扩展后的最优结构k+1 之间 扩展的部分
**单原子扩展增量: 那么每次扩展结构的时候,扩展部分可能只是 一个原子结构
多原子扩展增量:每次扩展结构的时候,扩展部分可能是 几个 原子结构


那么如何扩展结构呢
假设 前面为 结构k, 扩展的下一个结构为 结构k+1

1.结构扩展至少有三种,或者说每次的扩展得扩展增量会有下面三种情况
那么每次扩展结构的时候,可能只是扩展一个x,
但也很可能是扩展 几个x。

2单原子扩展增量:是**通过前一种结构k 直接按规则扩展 得到下一种结构k+1。**比如12345中有结构k为123,扩展为下一种结构k+1为1234.每次只扩展一个 原子单位,就是一个数字。

3.多原子扩展增量:**是通过前一种结构k 直接按规则扩展 得到下一种结构k+1。**比如12345中有结构k为12,扩展为下一种结构k+1为12 34,再下一种是 1234 56.也就是每次扩展 m个原子单位,但是m是确定的。

4.混合原子扩展增量:而更为常见和普遍的一种扩展是容易知道确定下一种结构k+1,而前一种结构k反而是不确定的。这时候需要通过后一种结构k+1去寻找 前一种结构k。这时候往往前一种结构k会有很多种情况。比如12345中有结构k+1为1234,这时候前一种结构k可能是1,也可能是12,也可能是123,甚至可能是1234。
这种情况很明显,扩展增量可能是 一个,两个,三个,若干个 原子单位的 组合。也就是同时包含单原子扩展和多原子扩展情况。

这里比字符串123456789,

  1. 每次结构扩展的时候,可以是扩展一个数字,
  2. 也有可能是 扩展 若干个数字,
  3. 也有可能 这些情况都存在。就是扩展
    一个数字,扩展两个数字,扩展 n-1个数字这些情况都存在。

针对这些情况,需要分别去由 结构k的最优,得到结构k+1的最优解。

  1. 每次结构扩展的一个数字的时候,就考虑一次。一般由 结构k->结构k+1
  2. 每次结构扩展的几个数字的时候,也考虑一次。一般由 结构k->结构k+1
  3. 当每次扩展数字不确定的时候,就需要分别考虑前面的所有情况,然后找到最优解。一般由 结构k+1 倒推出 结构k,期间是混合原子扩展增量。

核心:结构k 与扩展结构k+1 的对应关系
结构k 与扩展结构k+1 之间,可能是 一一对应,也就是结构k的扩展结构 结构k+1只有一种情况
或者说扩展出来的 结构k+1的 原结构k只能是一种情况。

但也有 结构k 与扩展结构k+1 之间,是 多对应一,也就是结构k的扩展结构 k+1 可能是多种情况。
或者说扩展出来的 结构k+1的 原结构k会有 多种 情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值