并不是很透彻,只是切掉了一道模板题。
[TOC]
不等式
w(i,j)w(i,j),对于∀a≤b≤c≤d∀a≤b≤c≤d,满足
那么就称它满足四边形不等式。 区间包含单调性
w(i,j)w(i,j),对于∀a≤b≤c≤d∀a≤b≤c≤d,满足
那么就称它满足区间包含单调性。 各种定理
定理一
如果有DP式
如果w(i,j)w(i,j)满足四边形不等式和区间包含单调性。
那么f(i,j)f(i,j)也满足四边形不等式和区间包含单调性。
定理二
设满足四边形不等式的f(i,j)f(i,j)的决策点为s(i,j)s(i,j),则
如果w(i,j)w(i,j)满足四边形不等式,当且仅当
以上就是主要的内容。
证明?上网查,或自己推,我懒得打了。(一般只要能够自己推出来就能够理解了)
例题(模板):HDU3506 Monkey Party
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
int n,nn;
int a[2001],sum[2001];
int f[2001][2001];
int s[2001][2001];
int main()
{
while (scanf("%d",&n)!=EOF)
{
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
memcpy(a+n+1,a+1,sizeof(int)*n);
nn=n<<1;
for (int i=1;i<=nn;++i)
sum[i]=sum[i-1]+a[i];
memset(f,127,sizeof f);
for (int i=1;i<=nn;++i)
f[i][i]=0,s[i][i]=i;
//以下注销掉的部分是没有用四边形不等式的方法
// for (int len=1;len<n;++len)
// for (int i=1;i+len<=nn;++i)
// {
// int j=i+len;
// for (int k=i;k<j;++k)
// f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]);
// }
for (int len=1;len<n;++len)
for (int i=1;i+len<=nn;++i)
{
int j=i+len;
for (int k=s[i][j-1];k<=s[i+1][j];++k)
{
int newvalue=f[i][k]+f[k+1][j]+sum[j]-sum[i-1];
if (newvalue<f[i][j])
{
f[i][j]=newvalue;
s[i][j]=k;
}
}
}
int ans=INT_MAX;
for (int i=1;i<=n;++i)
ans=min(ans,f[i][i+n-1]);
printf("%d\n",ans);
}
return 0;
}
总结
一般情况下,四边形不等式用来优化区间DP,将时间复杂度硬生生地降一个维。(可能光是看程序看不出来,事实上,每一轮的处理,可以计算一下内部循环的次数,你将会惊奇的发现那是O(n)O(n)的)
有时候,四边形不等式不只是优化区间DP,这样的题还没打过,如果打过了就再补充。