以前一直对四边形不等式优化望洋兴叹,今天终于鼓起勇气去学了一发。
大佬传送门,这位大佬讲的比较清楚、明白,我就不再在博客里多做赘述了。
总之,四边形不等式优化就是原来时间复杂度为 O(n3) 的状态转移方程优化到 O(n2) ,前提是转移的额外费用需要满足“区间包含的单调性”和“四边形不等式”两个性质。
回到这题,考虑把环拆成数列,直接把数组复制一份跟在后面就行了,之后就直接四边形不等式优化就行了。
附上AC代码:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=2010;
long long a[N],f[N][N],w[N][N],s[N][N],ans;
int n;
int main(void){
scanf("%d",&n);
for (int i=1; i<=n; ++i) scanf("%lld",&a[i]),a[i+n]=a[i];
for (int i=1; i<=2*n-1; ++i){
for (int j=i; j<=i+n&&j<=2*n; ++j) w[i][j]=w[i][j-1]+a[j];
s[i][i]=i,f[i][i]=0;
}
for (int len=2; len<=n; ++len)
for (int i=1; i<=n*2-len+1; ++i){
int j=i+len-1;
f[i][j]=1ll<<60;
for (int k=s[i][j-1]; k<=s[i+1][j]; ++k){
long long t=f[i][k]+f[k+1][j]+w[i][j];
if (t<f[i][j]) f[i][j]=t,s[i][j]=k;
}
}
ans=1ll<<60;
for (int i=1; i<=n; ++i) ans=min(ans,f[i][i+n-1]);
return printf("%lld\n",ans),0;
}