我试图解决https://www.spoj.com/problems/LISA/
在这个问题中,给出的表达式只有*和 . 放置支架最大值需要输出 .
喜欢
1+2*3+4*5 = (1+2)*(3+4)*5 = 105
2*0*3+7+1*0*3 = 2*((0*3+7+1*0)*3) = 42
我遇到的2D动态问题解决方法的实现如下 . 取每个数字是矩阵行和列并做从下到上的方法 .
f(ci,cj) = Max( f(i,j-1) operator c(i,j) , f( i+1,j-1) operator c(i,i) )
Like 3,5 = Max of [ (3,4) * (5,5) or (3,3)+(4,5) ]
= Max of [ 7*5 or 3+20 ]
= Max of [ 35,23 ] = 35
我无法证明我得到的结果是最大和正确的 . 如何证明以下解决方案是最大和最优的?
-----------------------------------
C1 C2 C3 C4 C5
C1 1 3 9 13 105
C2 2 6 14 70
C3 3 7 35
C4 4 20
C5 5
2 回答
这是我的实现:(它假设查询格式正确)
子问题是从第i个数到第j个数的结果的最佳最小和最小结果 . 通过计算每个子阵列上的结果的最小值和最大值来确保最优性,然后应用递归关系 . 时间复杂度为O(n ^ 3),因为存在O(n ^ 2)个子问题并且每个都需要O(n) .
编辑:
说明:
对于动态编程,确定子问题是什么以及子问题如何与其他子问题相关是至关重要的 . 对于这个问题,例如
n
数字(因此n - 1
运算符),子问题是:通过组合i
-number和j
-number(包括)之间的数字和运算符,可以获得的最小值/最大值是多少 .基本情况是
i = j
,我们只有一个数字,最小值/最大值本身 .对于任何
j > i
,此问题的子问题是k范围从i
到j - 1
左边部分的最小值和最大值(子问题用i
和k
作为两个 endpoints )和右边部分(子问题用k + 1
和j
作为两个) endpoints ) . 对于每个k
我们基本上做的是将k
-th运算符应用为最后一个运算符,因此我们可以为每个k
获得的最小值是最小值(operator
)最小值(最大值类似) . (请注意,运算符是*
或+
,它们是单调的,因此我们将最小值组合起来得到最小值和最大值以获得最大值 . 对于更多运算符(例如-
或/
)的更通用问题,我们可能需要考虑很多情况但是基本结构应该是相同的) . 因此,复发关系很简单minimum(i, j) = min(minimum(i, k) [operator] minimum(k + 1, j) for each k)
(same for max)
我们必须只解决每个子问题(总共
O(n^2)
)一次并缓存它(或按人们的说法记忆它),每个子问题都需要一个O(n)
循环来解决 . 因此时间复杂度为O(n^3)
.更深入地了解动态编程将真正帮助您解决所有类似的问题 . 如果您不确定在这样的环境中会发生什么,我建议您阅读一些相关内容 .
这个问题可以归类为记忆分而治之的分而治之的问题 .
想象一下你的字符串是
s = s1 op1 s2 op2 s3 op3 s4
现在你可以在每个
op
分区s
让我们说你在
op1
分区s
给你两个字符串:左字符串:
s1
和右字符串:
s2 op2 s3 op3 s4
.让我们说左字符串可以获得的最小值,最大值是
min1, max1
对于正确的字符串是:
min2, max2
.您可能认为
min1 op1 min2
是最小的,max1 op1 max2
是最大的但尚未完成 .
您需要为每个
op
执行此操作并累积min
和max
的值 . 为什么?因为op1
处的分区可能不是最佳的 .然后在所有这些分区中选择
min(mins)
和max(maxs)
你可以通过在Java中记住结果来递归地实现它,如: