动态编程的案例区分:需要示例!


19

我从事动态编程已有一段时间了。评估动态编程递归的规范方法是创建一个包含所有必要值的表,并将其逐行填充。有关简介,请参见例如Cormen,Leiserson等人:“算法简介”

我将重点放在二维(逐行填充)的基于表的计算方案上,并研究单元格依存关系的结构,即在计算另一个单元格之前需要完成哪些单元格。我们用表示Γ(i)单元格i依赖的单元格的索引集。请注意,Γ必须是无周期的。

我从计算出的实际函数中抽象出来,并专注于其递归结构。形式上,如果递归具有以下形式,则我认为它d动态编程

d(i)=f(i,Γ~d(i))

Γ d= { Ĵd Ĵ| ĴΓ d}˚F一些(可计算)函数,它不使用ð比通过其他Γ di[0m]×[0n]Γ~d(i)={(j,d(j))jΓd(i)}fdΓ~d

当限制的粒度粗糙区域(左侧,左上,上,右上,...当前单元格)的一个观察到有三个基本例(高达对称性和旋转)的有效动态编程递归,通知如何填充表:Γd

动态编程单元格依赖的三种情况

红色区域表示(近似)。情况一和二承认子集,情况三是最坏的情况(直到索引转换)。注意,并非严格要求整个红色区域都被Γ覆盖;表格每个红色部分中的一些单元格足以将其涂成红色。明确要求白色区域包含任何必需的单元格。ΓΓ

第一种情况的示例是编辑距离最长公共子序列第二种情况适用于Bellman&FordCYK。不太明显的例子包括:对角线而不是行(或列),因为它们可以旋转以适应所提出的情况;有关示例,请参见乔的答案

不过,对于情况三,我没有(自然的)例子!所以我的问题是:案例三的动态编程递归/问题有哪些示例?


2
案例3涵括例1和2
JeffE

不,尽管看起来看起来不是。例如,案例1实例在左上区域不能具有必需的单元格,而案例3实例具有具有在左上区域中的所需的细胞。我编辑了说明以进行澄清。
拉斐尔

Answers:


15

还有许多其他动态编程算法的示例根本无法满足您的模式。

  • 最长的子序列增长问题仅需要一个一维表。

  • 有几种自然的动态编程算法,它们的表需要三个或什至更大的维度。例如:在位图中找到最大面积的白色矩形。自然动态规划算法使用三维表。

  • 但最重要的是,动态编程与表无关;这是关于递归递归的。有很多自然的动态编程算法,其中用于存储中间结果的数据结构不是数组,因为展开的递归不在整数范围内。两个简单的示例是找到树中最大的独立顶点集,并找到两棵树的最大公共子树。一个更复杂的例子是(1+ϵ) Arora和Mitchell针对欧几里德旅行推销员问题近似算法。


感谢您的回答,但我将问题明确地限制在二维问题和基于表的规范计算方案(已编辑,使这一点更加清楚)。我知道更通用的框架,但目前对它不感兴趣。
拉斐尔

9
好的,但是我真的认为您没有抓住重点。
JeffE 2012年

由于有很多支持,我想我应该说清楚:这篇文章没有回答这个问题,实际上甚至没有尝试。
拉斐尔

2
@Raphael是正确的。我的“答案”不是答案,而是对该问题的批评,但是评​​论太久了。
JeffE 2012年

3

本着这种精神,计算阿克曼函数。要计算您需要知道某个较大k的A m n - 1 A m - 1 k 。第二个坐标减小,或者第一个坐标减小,第二个潜在地增大。A(m,n)A(m,n1)A(m1,k)k

由于列数是无限的,因此这不理想地满足要求,并且计算通常自上而下地进行存储,但我认为值得一提。


1
不,像中的嵌套并不能真正实现动态编程。呵呵,这太奇怪了,我必须检查一下我的定义是否以某种方式排除了这种情况。非原始递归DP,我的天哪A(m1,A(m,n1))
拉斐尔

1
不知道为什么这个答案被否决了,因为这是一个很好的答案。Ackermann函数非常适合动态编程。通常,为相同的参数重复计算的任何递归定义的函数都适合进行动态编程。要看到这一点,只需执行它并比较运行时间。使用普通的Ackermann函数进行计算需要花费数年的时间,而使用动态编程则需要数秒的时间。
朱尔斯

@Jules:规范表方案的问题是您不知道表大小是先验的(原始递归)边界。当然,您可以做备忘录,但不能以通常的方式做。所以是的,对于DP来说可能是可行的,但它不适合我的问题所关注的问题类别。
拉斐尔

1
我认为DP不需要先验地限制表的大小吗?实际上,正如JeffE提到的那样,缓存根本不必是表。它可以是任何关联的数据结构。DP实际上是一个非常非常简单的想法:您想计算一个递归定义的函数,但是该函数会在相同的参数上反复调用。DP是一种优化,在其中引入了缓存以确保每个案例仅计算一次。即使有两个有界整数的函数,也有很多函数不适合您的情况。
Jules

2

这并不完全适合案例3,但是我不知道您的案例中是否有任何一个捕获了用于教动态编程的非常普遍的问题:矩阵链乘法。为了解决这个问题(以及许多其他问题,这只是规范的问题),我们用对角线而不是逐行填充矩阵。

所以规则是这样的:

diagMatrix


1
这样写,的确不适合任何情况。但是,如果顺时针旋转45度,则会得到情况2(以及所有隐含属性)。对于从对角线到角落的其他示例也是如此。但感谢您提及它!
拉斐尔

@Raphael还不是很明显,它们是等效的,您可能想在问题中提及。
2012年

0

我知道这是一个愚蠢的例子,但我认为一个简单的迭代问题

在平方矩阵中找到数字的总和

可能有资格。传统的“对于每一行每一列”有点像您的情况3。


-1

这完全不是您要查找的搜索空间,但是我对我的想法有所帮助。

问题:

n×nMX中号

回答

这可以通过以下递归方式解决:

ķ=1个+ñ2。现在比较Xķķ。如果X<ķķ 我们可以丢弃任何元素 一世Ĵ 对于 ķ一世ñķĴñ 即,搜索空间减少了 1个/4。同样,当X>ķķ,搜索空间减少了 1个/4。因此,在第一次迭代之后,搜索空间的大小变为34ñ2。您可以进一步递归执行以下操作:我们进行3个比较:X 在其余三个象限的每个象限中使用中间元素,则剩余搜索空间的大小变为 343ñ2 等等。


1
这不是动态编程的实例,不是吗?
拉斐尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.