分析
原状态转移方程
f
[
i
]
[
j
]
=
m
a
x
{
f
[
i
]
[
k
]
+
f
[
k
+
1
]
[
j
]
+
w
(
i
,
j
)
}
f[i][j]=max\{f[i][k]+f[k+1][j]+w(i,j)\}
f[i][j]=max{f[i][k]+f[k+1][j]+w(i,j)}
其实可以发现,前缀和
w
(
i
,
j
)
w(i,j)
w(i,j)满足四边形不等式,所以也可以发现f数组也是满足四边形不等式的,所以可以记录f数组的最优中间点,时间优化到
O
(
n
2
)
O(n^2)
O(n2),空间依然是
O
(
n
2
)
O(n^2)
O(n2),这就是非动规方法的好处
代码
#include <cstdio>
int a[3001],f[3001][3001],s[3001][3001],n;
int in(){
int ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
n=in();
for (int i=1;i<=n;i++) a[i]=a[i-1]+in(),s[i][i]=i;
for (int len=1;len<n;len++)
for (int i=1;i<=n-len;i++){
int j=i+len;
f[i][j]=233333333;
for (int k=s[i][j-1];k<=s[i+1][j];k++)//从两个离答案最近的中间点求答案
if (f[i][j]>f[i][k]+f[k+1][j]+a[j]-a[i-1]){
f[i][j]=f[i][k]+f[k+1][j]+a[j]-a[i-1];//动态规划
s[i][j]=k;//记录最优的中间点
}
}
return !printf("%d",f[1][n]);
}