我的表达式由用加号和减号分隔的数字组成。 我需要在数字之间加上大括号来获得这个表达式的最大结果。 我试图获得这个问题的多项式算法,但我需要一些建议或提示如何实现它。 我发现了类似here的内容,但我不知道如何修改它。
编辑: 我认为这个想法可能类似于这个
getMax(inp)
{
if(|inp| == 1)
return inp[1] // base case
else
val = 0;
for(k=2; k < |inp|; k+=2)
val = max{val, getMax(inp[:k]) + getMax(inp[k+1:])}
}
答案 0 :(得分:5)
一种策略是使用动态编程来选择最后执行的最佳操作。这将表达式分为两部分。
如果操作是添加操作,则在每个部件上递归调用以查找每个部件的最大值。
如果操作是减法,你想要找到第一部分的最大值和第二部分的最小值。
这里有一些非memoized代码,只是为了说明重复是如何工作的(注意i
只迭代操作的索引,选择打破表达式的最佳位置):
import re
def T(s, f1=max, f2=min):
if len(s) == 1:
return int(s[0])
return f1(
T(s[:i], f1, f2)+T(s[i+1:], f1, f2)
if s[i]=='+' else
T(s[:i], f1, f2)-T(s[i+1:], f2, f1)
for i in xrange(1, len(s), 2))
def solve(expr):
return T(re.split('([+-])', expr))
print solve('1-2+1') #0 ((1-2)+1)
print solve('1-22-23') #2 (1-(22-23))
实现自下而上的动态编程有点棘手,因为填充表格的理想顺序有点不常规。最简单的方法是使DP在{{1}}附近,表示从T(k, i)
操作数&#34;开始的k
个操作数的表达式的最大值/最小值。使用分别在i
和O
中分隔运算符和数字的匿名概念,示例代码为:
N
答案 1 :(得分:2)
让运营商成为O[0]
,O[1]
,...,O[K-1]
。设数为N[0]
,N[1]
,...,N[K]
。 (还有一个数字而不是运算符)。
如果M[op, i, j]
为{{{},则i
是从数字j
开始,从数字op
(包括两端)结束的子表达式可实现的最大值{1}},+
为op
时的最小值。
因此-
是整个表达式可以采用的最大值。
M[+, 0, K]
满足递归关系:
M
此处M[+, i, i] = M[-, i, i] = N[i]
M[+, i, j] = max(M[+, i, k] O[k] M[O[k], k+1, j) for k in i...j-1)
M[-, i, j] = min(M[-, i, k] O[k] M[-O[k], k+1, j) for k in i...j-1)
表示A O[k] B
或A + B
取决于A - B
,而O[k]
表示-O[k]
,如果-
是{{} 1}}和O[k]
如果+
是+
。
基本上,您正在尝试找到将表达式拆分为最大化或最小化整体结果的最佳位置。当您考虑O[k]
运算符时,您会从最大化切换到最小化,反之亦然,在右侧。
这些递归关系可以通过动态编程直接评估,方法是为-
建立一个大小为2 *(K + 1)*(K + 1)的3维表,其中K是数字运营商。
总的来说,这个算法是O(K ^ 3)。