这是蓝书区间DP的第二道例题,我们以区间长度为阶段,由于 第length阶段的最大值有可能由 (length-1)阶段的两个比较小的负数相乘得到,所以只存一个阶段的最大值不满足“最优子结构”的性质,所以用f[l][r][0] 和 f[l][r][1] 分别表示区间起始位置为 l,r 的最大值与最小值, 形成一个子结构。
对于状态的转移,每一个阶段的 [l,r] 都由 [l,k], [k+1,r]合并而来所以k作为区间的划分是决策集合。而第一步先枚举每一个边删除再进行区间DP是O(n^4)的时间复杂度,如果把环拆开,复制形成两倍长的链就能把时间复杂度优化到O(n^3)
上ac代码:
import sys
inf = 32768
n = int(sys.stdin.readline())
ls = list(sys.stdin.readline().split())
ls,op = [int(ls[i]) for i in range(1,2*n,2)], [ls[i] for i in range(0,2*n,2)]
ls,op = [0]+ls+ls, [0]+op+op
f = [[[-inf,inf] for i in range(2*n+1)] for j in range(2*n+1)]
for i in range(2*n+1):
f[i][i][0] = f[i][i][1] = ls[i]
for length in range(2, n+1):
for l in range(1, 2*n - length + 2):
r = l + length - 1
for k in range(l,r):
x,y,a,b = f[l][k][0], f[l][k][1], f[k+1][r][0], f[k+1][r][1]
f[l][r][0] = max(f[l][r][0], x + a if op[k+1] == 't' else max(x*a,x*b,y*a,y*b))
f[l][r][1] = min(f[l][r][1], y + b if op[k+1] == 't' else min(x*a,x*b,y*a,y*b))
ans = -inf
for l in range(1, n+1):
ans = max(ans, f[l][l+n-1][0])
print(ans)
res = []
for l in range(1, n+1):
if f[l][l+n-1][0] == ans:
res.append(l)
print(*res)