dp优化1——浅谈四边形不等式优化

来源:互联网 发布:windows 10 安装.net 编辑:程序博客网 时间:2024/05/16 13:05

形式1

随手来一个dp式,

f[i,j]=min{f[i,k1]+f[k,j]}
,谁来说说这个dp的时间复杂度,看上去似乎是n立方的,但实际上如何呢?让我们拨开重重迷雾,找到真相。

引入——四边形不等式

内容:abcd,若w满足

w[a,c]+w[b,d]w[a,d]+w[b,c]
,则称w满足四边形不等式。

定理一

s[i,j]=min{k|f[i,k1]+f[k,j]}
,什么意思呢?就是s[i,j]表示令f[i,k1]+f[k,j]取最小值的k。
定理一内容:若f满足四边形不等式,那么
s[i,j1]s[i,j]s[i+1,j]

定理一证明:
由对称性我们只需要证明s[i,j1]s[i,j],假设我们现在有两个决策点,
分别为k1,k2,k1k2j1j,同时设fk[i,j]表示以k为决策点转移过来的f[i,j]的值,由f满足四边形不等式可得,
f[k1,j1]+f[k2,j]f[k1,j]+f[k2,j1]
,两边同时加上
f[i,k11]+f[i,k21]
fk1[i,j1]+fk2[i,j]fk1[i,j]+fk2[i,j1]
,接着移项得
fk1[i,j1]fk2[i,j1]fk1[i,j]+fk2[i,j]
,若此时决策点k1比决策点k2要优,那么不等式右边小于等于0,也就是说,若k1这个决策点优于k2的条件是在f[i,j1]的决策中k1也要优于k2,那么对于kl<s[i,j1],这个k就不可能是最优决策点。证毕。

揭密——时间复杂度

首先枚举一个长度l,然后求所有的f[i,i+l1]

i=1nl+1(s[i+1,i+l1]s[i,i+l2])=s[nl+2,n]s[1,l1]

解释一下为什么是这样的,因为将每一项的s都写出来,可以发现除末尾项,每一项的那个加上的s项总是跟后面的那一项的减去的s项抵消。
然后再乘上外面那层枚举长度的l,所以最后时间复杂度为n方的。

形式二

f[n]=min{f[i,k1]+f[k,j]+w[i,j]},0,i<ji=ji>j

区间包含单调性

abcd,都有w[a,d]w[b,c]。或将不等式变号,则称w满足区间包含单调性。

定理二

若w同时满足四边形不等式和区间包含单调性,那么f也满足四边形不等式和区间包含单调性。
定理二证明:若w满足区间包含单调性,那么f显然也满足区间包含单调性(想想为什么)
下证f满足四边形不等式,我们可以得到一个显然的东西,当区间长度小于等于2时,显然成立。下面我们讨论区间长度大于2的情况,则a<bc<d,然后我们再假设所有被区间[a,d]包含的子区间都满足四边形不等式。此时分两种情况讨论:
情况①:
当b=c时,令k=s[a,d],暂且设kb,因为由对称性,所以这不是重点。

f[a,b]+f[b,d]f[a,k1]+f[k,b]+w[a,b]+f[b,d]f[a,k1]+f[k,b]+f[b,d]+w[a,d]f[a,k1]+f[k,d]+f[b,b]+w[a,d]f[a,k1]+f[k,d]+w[a,d]f[a,d]

情况②:
此时a<b<c<d,令y=s[b,c],z=s[a,d],再假设yz,则此时a<b<y<z

f[a,c]+f[b,d]f[a,y]+f[y+1,c]+w[a,c]+f[b,z]+f[z+1,d]+w[b,d]f[a,y]+f[b,z]+f[y+1,c]+f[z+1,d]+w[a,d]+w[b,c]f[a,z]+f[b,y]+f[y+1,c]+f[z+1,d]+w[a,d]+w[b,c]=f[a,d]+f[b,c]

定理三

w满足四边形不等式但且仅当

w[i,j]+w[i+1,j+1]w[i+1,j]+w[i,j+1]
,不要问我为什么我现在已经脑力不支了,留个坑先。

例题(较为经典,相信大家都切了)

题目描述
在一个环状跑道上摆放着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.

原创粉丝点击