动态规划学习

DP(又称动态规划) 学了两年都没学明白,为了最后半年的区域赛,系统的学一下,更好的准备接下来的比赛.

#动态规划部分简介

动态规划应用于子问题重叠的情况:

  1. 要去刻画最有界的结构特征;
  2. 尝试递归地定义最优解的值(就是我们常说的考虑从 i − 1 i-1 i1 i i i)
  3. 计算最优值
  4. 利用计算出的信息构造一个最优解

经典例题

给定一段钢条,和不同长度的价格,问如何切割使得总价格最大。

为了求解规模为 n n n的原问题,我们先求解形式完全一样,但规模更小的子问题。 即当完成首次切割后,我们将两段钢条看成两个独立的钢条切割问题实例。 我们通过组合相关子问题的最优解,并在所有可能的两段切割方案中选取组合收益最大者,构成原问题的最优解。

最优子结构: 问题的最优解由相关自问题的最优解组合而成
动态规划的两种实现方法:

  • 带备忘的自定向下法(记忆化搜索);
  • 自底向上法(将子问题按照规模排序,类似于递推)。
    算导用子问题图上按照逆拓扑排序求解子问题,引出记忆化搜索。
    重构解(输出方案): 转移的时候记录最优子结构的位置。

矩阵链乘法

给出 n n n个矩阵的序列,希望计算他们的乘积,问最少需要多少次乘法运算?
(认为 p × q p \times q p×q的矩阵与 q × r q \times r q×r的矩阵相乘的代价是 p × q × r p \times q \times r p×q×r
完全括号化方案是指要给出谁先和谁乘。

动态规划原理

两个要素:

最优子结构

具有最优子结构也可能是适合用贪心的方法求解。
注意要确保我们考察了解最优解中用到的所有子问题。

  1. 证明问题最优解的第一个组成部分是作出一个选择;
  2. 对于一个给定问题,在其可能的第一步选择中,你界定已经知道那种选择才会得到最优解。你现在并不关心这种选择具体是如何得道的,只是假定已经知道了这种选择;
  3. 定可获得的最优解的选择后,确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间;
  4. 证明作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解。方法是反证法,考虑加入某个子问题的解不是其自身的最优解,那么就可以从原问题的解中用该子问题的最优解替换掉当前的非最优解,从而得到原问题的一个更优的解,从而与原问题最优解的假设矛盾。
    要保持子问题空间尽量简单,只在必要时扩展。

最优子结构的不同体现在两个方面:

  1. 原问题的最优解中涉及多少个子问题;
  2. 确定最优解使用哪些子问题时,需要考察多少种选择。
    子问题图中每个定点对应一个子问题,而需要考察的选择对应关联至子问题顶点的边。
经典问题:
  • 无权最短路径:具有最优子结构性质。
  • 无权最长路经:此问题不具有,是 NPC 的。区别在于,要保证子问题无关,即同一个原问题的一个子问题的解不影响另一个子问题的解。相关:求解一个子问题时用到了某些资源,导致这些资源在求解其他子问题时不可用。
子问题重叠

子问题空间要足够小,即问题的递归算法会反复的求解相同的子问题,而不是一直生成新的子问题。

重构最优解

存表记录最优分割的位置,就不用重新按照代价来重构。

最长公共子序列

子序列不连续
每个 c [ i ] [ j ] c[i][j] c[i][j]只依赖于 c [ i − 1 ] [ j ] c[i-1][j] c[i1][j] c [ i ] [ j − 1 ] c[i][j-1] c[i][j1] c [ i − 1 ] [ j − 1 ] c[i-1][j-1] c[i1][j1]
记录最优方案的时候可以不需要额外建表(优化空间),因为重新选择一遍(转移过程)也是 O ( 1 ) O(1) O(1)的。

最优二叉搜索树

给二叉搜索树的每个节点定义一个权值,问如何安排使得权值和深度的乘积最小
考虑当一棵子树成为了一个节点的子树时,答案(期望搜索代价)有何变化?
由于每个节点的深度都增加了1,这棵子树的期望搜索代价的增加值应为所有概率之和。

动态规划:状态空间是 O ( n t ) O(n^t) O(nt)的,每一项依赖其他 O ( n e ) O(n^e) O(ne)项。

最长连续不下降子序列

对n个数求它的最长不下降子序列,也就是求最长的上升(一个数比一个数大)子序列有多长。
因为是连续的,所以只要遇上一个元素比较即可.

int a[MAXN];
int dp() {
	int now = 1, ans = 1;
	for (int i = 2; i <= n; i++) {
			if (a[i] > a[i - 1])
  				now++;
			else
  				now = 1;
			ans = max(now, ans);
	}
 	return ans;
}

未完待续 … \ldots

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值