for l inrange(1, N+1):for i inrange(N-l+1): j = i+l-1if l<=2: f[i][j] = (s[i]==s[j])else: f[i][j] = (f[i+1][j-1] and s[i]== s[j])if f[i][j] and l>len(res): res = s[i:j+1]return res
N = len(nums)
f = [[0]*(N+1) for _ in range(N+1)]
for l in range(N):
for i in range(N-l):
j = i+l
f[i][j] = max(nums[i]-f[i+1][j],
nums[j]-f[i][j-1])
return f[0][N-1] >= 0
# Memoization
@cache
def maxScore(i, j):
if i==j: return nums[i]
left = nums[i] - maxScore(i+1, j)
right = nums[j] - maxScore(i, j-1)
return max(left, right)
return maxScore(0, len(nums)-1) >= 0
cuts = [0] + sorted(cuts) + [n]
N = len(cuts)
f = [[float('inf')]*N for _ in range(N)]
for l in range(1, N):
for i in range(N-l):
j = i+l
if l==1:
f[i][j] = 0
continue
for k in range(i+1, j):
f[i][j] = min(f[i][j],
f[i][k]+f[k][j]+cuts[j]-cuts[i])
return f[0][-1]
# Memoization
cuts = [0] + sorted(cuts) + [n]
N = len(cuts)
@cache
def minCost(i, j):
if j-i==1: return 0
res = float('inf')
for k in range(i+1, j):
left = minCost(i, k)
right = minCost(k, j)
res = min(res, left+right+cuts[j]-cuts[i])
return res
return minCost(0, N-1)
有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。戳破第 i 个气球,
你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。
这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。
如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。
求所能获得硬币的最大数量。
输入:nums = [3,1,5,8]
输出:167
解释:
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167
nums = [1] + nums + [1]
n = len(nums)
f = [[0]*n for _ in range(n)]
for l in range(n):
for i in range(n-l):
j = i+l
for k in range(i+1, j):
f[i][j] = max(f[i][j],
f[i][k]+f[k][j]+nums[i]*nums[k]*nums[j])
return f[0][-1]
# Memoization
nums = [1] + nums + [1]
@cache
def maxScore(i, j):
if i>=j-1: return 0
res = 0
for k in range(i+1, j):
left = maxScore(i, k)
right = maxScore(k, j)
res = max(res, left+right+nums[i]*nums[j]*nums[k])
return res
return maxScore(0, len(nums)-1)
N = len(s)
f = [[0]*N for _ in range(N+1)]
for l in range(N):
for i in range(N-l):
j = i+l
f[i][j] = f[i+1][j] + 1
for k in range(i+1, j+1):
if s[i]==s[k]:
f[i][j] = min(f[i][j], f[i][k-1]+f[k+1][j])
return f[0][-1]
# Memoization
@cache
def minCost(i, j):
if i>j: return 0
res = minCost(i+1, j) + 1
for k in range(i+1, j+1):
left = minCost(i, k-1)
right = minCost(k+1, j)
if s[k]==s[i]:
res = min(res, left+right)
return res
return minCost(0, len(s)-1)
N = len(boxes)
f = [[[0]*(N+1) for _ in range(N+1)] for _ in range(N+1)]
for l in range(N):
for i in range(N-l):
j = i+l
for p in range(N-j):
if i<j and boxes[j]==boxes[j-1]: # pruning
f[i][j][p] = f[i][j-1][p+1]
continue
f[i][j][p] = f[i][j-1][0]+(p+1)**2
for k in range(i, j):
if boxes[k]==boxes[j]:
f[i][j][p] = max(f[i][j][p],
f[i][k][p+1]+f[k+1][j-1][0])
return f[0][N-1][0]
# Memoization
@cache
def maxScore(i, j, p):
if i>j: return 0
while i<j and boxes[j]==boxes[j-1]:
j -= 1
p += 1
res = maxScore(i, j-1, 0) + (p+1)**2
for k in range(i, j):
if boxes[k]==boxes[j]:
left = maxScore(i, k, p+1)
right = maxScore(k+1, j-1, 0)
res = max(res, left+right)
return res
return maxScore(0, len(boxes)-1, 0)