四邊形不等式優化DP
阿新 • • 發佈:2018-02-20
pla mes npos 石子歸並 分享 max turn 四邊形 namespace
(沒啥卵用)
記錄一下,以免忘了
對於一個形如
\[dp[i][j]=min(dp[i][k]+dp[k][j]+w[i][j])\]
的轉移方程(註意取最大值時不一定滿足四邊形不等式)
定理1
若對於\(a \leq b\leq c \leq d\)且\(w_{b,c}\leq w_{a,d}\)
那麽我們稱\(w\)關於區間包含關系單調
定理2
若對於\(a \leq b\leq c \leq d\)且\(w_{a,c}+w_{b,d}\leq w_{b,c}+w_{a,d}\)
則稱\(w\)滿足四邊形不等式
性質1
若\(w\)滿足四邊形不等式,當且僅當\(w_{i,j}+w_{i+1,j+1}\leq w_{i+1,j}+w_{i,j+1}\)
(沒啥卵用)
性質2
若\(w\)滿足四邊形不等式,且關於區間包含關系單調
則\(dp\)也滿足四邊形不等式
性質3
設\(s_{i,j}\)為\(dp_{i,j}\)的決策點,若\(dp\)滿足四邊形不等式
那麽\(s_{i,j-1}\leq s_{i,j} \leq s_{i+1,j}\)
證明
放一個不錯的博客
例題
石子歸並加強版
其實這題並不是極限數據,再強一點的可以去百度SDOI2008石子歸並,據說要用平衡樹維護某G姓算法
#include<cstdio> #include<cstring> const int MAXN=1e5+10,INF=1e8+10; using namespace std; inline char nc() { static char buf[MAXN],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin)),p1==p2?EOF:*p1++; } inline int read() { char c=nc();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();} return x*f; } int dp[3001][3001],sum[MAXN],s[3001][3001]; int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif int N=read(); for(int i=1;i<=N;i++) sum[i]=read(),sum[i]+=sum[i-1],s[i][i]=i; for(int i=N;i>=1;i--) { for(int j=i+1;j<=N;j++) { int mn=INF,mnpos=0; for(int k=s[i][j-1];k<=s[i+1][j];k++) { if(dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1] < mn) { mn=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]; mnpos=k; } } dp[i][j]=mn; s[i][j]=mnpos; } } printf("%d",dp[1][N]); return 0; }
四邊形不等式優化DP