[Algo] Maximum Expression Value 表达式最大值 - SegmentFault
给定一个整数数组,要求在数字之间任意添加乘号,加号和括号,使得最后表达式结果最大。比如
1121,最大值为(1+1)*(2+1),所有数字都是正数。
动态规划
复杂度
时间O(n^2) 空间O(N^2)
思路
先假设没有乘号,那最大值就是所有数加起来,然后我们考虑将其分段加入乘号,如果某一段是加号,和其他段相乘,那我们就认为那段加号的就被加了个括号。所以我们分段的过程其实就加了括号了。但是这么多数字我们可以分很多不同段,如果用搜索的话难免会有重复计算,所以这里用到动态规划,假设dp[i][j]表示总长为i的一段数字,其中前j长的哪一段中可以包含乘号,所能产生的最大值,这么一来,假设题目所给的数字有n个,那dp[n][n]就是这所有的数字组合起来既有加号又有乘号的式子的最大值了。再假设sum(k, i)表示所给数字从第k个到第i个数字的和。递推式为dp[i][j] = max(dp[i][j], dp[k][j - 1] * sum(k + 1, i)),这里i >= k >= j。其中后半部分dp[k][j - 1] * sum(k + 1, i)表示,我们把总长为i的数字分割成前k个,和k + 1到最后两部分。前半部分最大值已知,我们用它来乘以后半部分的和,用这种方法来决定哪一段只用加号。
举例说明,假设所给数字为
3 2 6 我们可以有最大值3 * 2 * 6 = 36,一开始我们有:
sum: 3 5 11 j=0 j=1 j=2 j=3 dp: i=0 0 0 0 0 i=1 0 3 0 0 i=2 0 5 0 0 i=3 0 11 0 0 由于总长为i,其中前1位数字可以包含乘号的情况,就是所有数字都不包含乘号,所以最大值就是累加值。然后我们看总长为2开始(总长为1就是第一个数,没有计算的必要),前2位数字可以包含乘号的情况,这里我们可以有分割点k = 1时,是3 + 2 = 5和k = 2时是3 * 2 = 6两种情况(k表示从第k位开始只有加号)。这时最大值6,更新dp[2][2]。
j=0 j=1 j=2 j=3 dp: i=0 0 0 0 0 i=1 0 3 0 0 i=2 0 5 6 0 i=3 0 11 0 0 然后我们看总长为3开始(总长为1就是第一个数,没有计算的必要),前2位数字可以包含乘号的情况。这里k=2时,3 * (2 + 6) = 24, k=3时,6 * 6 = 36(第一个6是dp[2][2],第二个6是我们所给数字中的6)
j=0 j=1 j=2 j=3 dp: i=0 0 0 0 0 i=1 0 3 0 0 i=2 0 5 6 0 i=3 0 11 24 36 更新完dp[3][3]我们也就计算完所有情况了,这时可知最大值是36.
注意
全局最大max在第一个用于累加的for循环后,要置为dp[n][0],否则我们会把全部数字加起来这个组合给漏掉。
Read full article from [Algo] Maximum Expression Value 表达式最大值 - SegmentFault
No comments:
Post a Comment