形式1
随手来一个dp式,
引入——四边形不等式
内容:
∀a≤b≤c≤d
,若
w
满足
定理一
设
定理一内容:若f满足四边形不等式,那么
定理一证明:
由对称性我们只需要证明 s[i,j−1]≤s[i,j] ,假设我们现在有两个决策点,
分别为 k1,k2,而且k1≤k2≤j−1≤j ,同时设 fk[i,j] 表示以k为决策点转移过来的 f[i,j] 的值,由f满足四边形不等式可得,
f[i,k1−1]+f[i,k2−1] 得
揭密——时间复杂度
首先枚举一个长度l,然后求所有的
f[i,i+l−1]
解释一下为什么是这样的,因为将每一项的s都写出来,可以发现除末尾项,每一项的那个加上的s项总是跟后面的那一项的减去的s项抵消。
然后再乘上外面那层枚举长度的l,所以最后时间复杂度为n方的。
形式二
区间包含单调性
∀a≤b≤c≤d ,都有 w[a,d]≤w[b,c] 。或将不等式变号,则称w满足区间包含单调性。
定理二
若w同时满足四边形不等式和区间包含单调性,那么f也满足四边形不等式和区间包含单调性。
定理二证明:若w满足区间包含单调性,那么f显然也满足区间包含单调性(想想为什么)
下证f满足四边形不等式,我们可以得到一个显然的东西,当区间长度小于等于2时,显然成立。下面我们讨论区间长度大于2的情况,则
a<b≤c<d
,然后我们再假设所有被区间[a,d]包含的子区间都满足四边形不等式。此时分两种情况讨论:
情况①:
当b=c时,令k=s[a,d],暂且设
k≤b
,因为由对称性,所以这不是重点。
则
情况②:
此时 a<b<c<d ,令y=s[b,c],z=s[a,d],再假设 y≤z ,则此时 a<b<y<z
则
定理三
w满足四边形不等式但且仅当
例题(较为经典,相信大家都切了)
题目描述
在一个环状跑道上摆放着N堆石子,现在要将所有的石子有次序地合并成一堆。规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。问最少的总得分是多少?
输入
第一行为石子堆数N。
从第2行到第N + 1行,每行一个正整数。第i个数表示第i堆石子的石子数。
输出
在第一行输出一个整数,表示最少的总得分。
样例输入
4
4
5
9
4
样例输出
43
数据范围限制
在40%的数据中,1 ≤ N ≤ 100
在60%的数据中,1 ≤ N ≤ 200
在100%的数据中,1 ≤ N ≤ 2000
保证输入数据中每堆石子的石子数不超过10000
我们是普通人,不要想着用什么GarsiaWachs算法优化到
O(nlogn)
,
普通人的做法:因为是环状,首先复制一份,设
f[i,j]
,表示将第i堆石子合并到第j堆石子能得到的最少的分数,然后用四边形不等式随便弄一下。
无优化代码如下:时间复杂度:
O(n3)
uses
math;
var
n:0..2000;
m,i,j,k,len,minest:longint;
a,w:array [0..5000] of longint;
f:array [0..3000,0..3000] of longint;
begin
readln(n);
for i:=1 to n do
begin
readln(a[i]);
w[i]:=w[i-1]+a[i];
end;
for i:=1 to n do
w[n+i]:=w[i+n-1]+a[i];
for len:=2 to n do
for i:=1 to 2*n-len+1 do
begin
j:=i+len-1;
f[i,j]:=maxlongint;
for k:=i to j-1 do
f[i,j]:=min(f[i,j],f[i,k]+f[k+1,j]+w[j]-w[i-1]);
end;
minest:=maxlongint;
for i:=1 to n do
minest:=min(minest,f[i,i+n-1]);
writeln(minest);
end.
四边形不等式优化:时间复杂度: O(n2)
uses
math;
var
f,s:array[1..4000,1..4000]of longint;
n,i,j,len,k,minest:longint;
a,w:array[0..4000]of longint;
begin
read(n);
for i:=1 to n do
begin
readln(a[i]);
w[i]:=w[i-1]+a[i];
end;
for i:=1 to n do
w[n+i]:=w[i+n-1]+a[i];
for len:=1 to n do
for i:=1 to n+n-len+1 do
begin
j:=i+len-1;
if len=1 then
s[i,j]:=i
else
for k:=s[i,j-1]to s[i+1,j]do
if(f[i,j]=0)or(f[i,k]+f[k+1,j]+w[j]-w[i-1]<f[i,j])then
begin
s[i,j]:=k;
f[i,j]:=f[i,k]+f[k+1,j]+w[j]-w[i-1];
end;
end;
minest:=maxlongint;
for i:=1 to n do
minest:=min(minest,f[i,i+n-1]);
write(minest);
end.
the end
由于我的水平有限,难免会有些写错的地方,希望大家批评指正,多多包容,thank you for your patience.