对四边形不等式优化dp的理解
四边形不等式适用于优化最小代价子母树问题,即f[i][j]=max/min(f[i][k-1]+f[k][j])+w[i][j],类似枚举中间点的dp问题,典型例题石子归并;
如果w函数满足区间包含的单调性和四边形不等式,那么函数f也满足四边形不等式,如果f满足四边形不等式,s[i][j]=max/min{t|f[i][j]=f[i][k-1]+f[k][j]}+w[i][j],也就是s[i][j]是f[i][j]取得最优解的中间点,s[i][j]具有单调性;
即s[i][j-1]<=s[i][j]<=s[i+1][j],所以k从[s[i][j-1],s[i+1][j]]枚举就好了,缩小了范围,将复杂度由O(n^3)降到了O(n^2)。
附石子规并四边形不等式优化标程:
#include<bits/stdc++.h> #define len 3010 #define inf 99999999 using namespace std; int n,a[len],f[len][len],sum[len],s[len][len]; void in(int &x) { char c=getchar();x=0; while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); } int main() { in(n); for(int i=1;i<=n;i++) { in(a[i]); sum[i]=sum[i-1]+a[i]; s[i][i]=i; } for(int le=1;le<n;le++) for(int l=1;l<=n-le;l++) { int r=l+le; f[l][r]=inf; for(int k=s[l][r-1];k<=s[l+1][r];k++) if(f[l][r]>f[l][k]+f[k+1][r]+sum[r]-sum[l-1]) { f[l][r]=f[l][k]+f[k+1][r]+sum[r]-sum[l-1]; s[l][r]=k; } } cout<<f[1][n]; return 0; }