给定一组实数值A[1..n,1..n]
,我希望找到子数组
B = A[i..j,s..t]
1 <= i <= j <= n,
和1 <= s <= t <= n
使B
中的数字总和最大化。是否可以使用动态编程解决这个问题?我和奥胡斯大学的其中一位OR教授交谈过,他不知道该怎么做,并说他很难看出它如何具有最佳的子结构质量。
但是有可能吗?如果有,怎么样?如果没有,为什么?
我已经知道一种算法在O(n^3)
时间运行,通过将其减少到n(n+1)/2
复杂度O(n)
的子问题,但这看起来有点慢。我知道最佳算法会在Omega(n)
时间内运行,但我希望动态编程可以用于在O(n^2)
时间运行。
原始问题汇总
我添加了这一部分,因为我觉得有些人误解了我的问题。最初的问题是:
O(n^2)
时间内解决上述问题?如果有,怎么样?如果不是,为什么不呢?其他问题:
我在这里添加了一个新问题。稍后可能会添加更多内容:
B = A[1..m,1..m]
A[1..n,1..n]
的子m < n
,那么数组B
的最佳解决方案最多就像A
,因为同样的解决方案在A
中是可行的。因此,要使用动态编程,可以合理地问:A[1..i,1..i]
的最佳子阵列与A[1..i+1,1..i+1]
的最佳子阵列之间的关系是什么?答案 0 :(得分:3)
一个可能有用的优化是当你可以计算得分不可能超过当前最佳时,跳过检查a,b对。
例如,一种方法是:
如果您还在阵列M上运行Kadane算法并首先测试生成的a,b对,这可能效果最好。
在最好的情况下(例如图像中包含黑色背景和白色矩形),这将在O(n ^ 2)中找到答案,但对于更复杂的输入,它仍然需要O(n ^ 3)
警告:在实践中,这个技巧可能只会对一小部分输入有所帮助,因为降低了大多数人的成本......
编辑: 一些额外的解释:
对于第i行,M [i]包含可以从A [i..i,x..y]形式的任何高度1矩形获得的最大值。
我们定义一个新的数组P [i](在上面的描述中称为垂直前缀和)。
P[0]=0
P[i+1]=M[i]+P[i]
对于给定的行s和t的选择,我们可以通过计算和来快速估计可以从形式A [s..t,x..y]的任何矩形获得的最高值(M [ i]我在范围内(s,t + 1))。这实际上给了我们一个形状的值:
... Row s
....
.......
.... Row t
通过从s和t之间的每一行取最佳高度1矩形而形成。
数组P [i]是有用的,因为P [i] = sum(范围(i)中j的M [j]),因此我们可以计算和(M [i] in i的范围(s,t)在O(1)时间内+1))= P [t + 1] -P [s]。
答案 1 :(得分:1)
从The Algorithmist开始,如果您有一个n×n数组,那么您可以做的最好是O(n ^ 3):
假设您有一个n乘2的数组,则可以将其降低到O(n ^ 2)。如上所述,关键是使用Kadane's algorithm