'''
核心思想
将原来序列拓展成2倍长度,在拓展区间上做区间DP
将环问题转换为线性区间问题
'''
N = int(input())
arr = list(map(int, input().split()))
# 把原来的序列拓展成2倍,然后在拓展之后的序列上进行区间DP,把换拆成链
arr = arr * 2
# dp(i,j)表示从i到j的区间中的石子合并成一个石子的所有方案中最小的开销
dp = [[0] * (2*N) for _ in range(2*N)]
s = [val for val in arr]
for i in range(1, len(s)):
s[i] += s[i - 1]
for i in range(2*N - 1, -1, -1):
for j in range(i, min(i+N, 2*N)):
if i != j:
dp[i][j] = 0x7fffffff
for k in range(i, j):
sum = s[j] if i == 0 else s[j] - s[i - 1]
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum)
# 筛选出长度是N的区间, 选最小的值
ans = 0x7fffffff
for i in range(N):
ans = min(ans, dp[i][i+N-1])
print(ans)
# dp(i,j)表示从i到j的区间中的石子合并成一个石子的所有方案中最大的开销
dp = [[0] * (2*N) for _ in range(2*N)]
s = [val for val in arr]
for i in range(1, len(s)):
s[i] += s[i - 1]
for i in range(2*N - 1, -1, -1):
for j in range(i, min(i+N, 2*N)):
if i != j:
dp[i][j] = 0
for k in range(i, j):
sum = s[j] if i == 0 else s[j] - s[i - 1]
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + sum)
# 筛选出长度是N的区间, 选最大的值
ans = 0
for i in range(N):
ans = max(ans, dp[i][i+N-1])
print(ans)
AcWing 区间DP相关问题 1068. 环形石子合并
猜你喜欢
转载自blog.csdn.net/xiaohaowudi/article/details/107730176
今日推荐
周排行