您的位置:首页 > 其它

模型化理解单调队列优化和斜率优化DP

2016-06-30 20:32 453 查看
设A(x),B(x),C(x),D(x)为仅关于x的一元函数



单调队列DP



DP转移方程需要满足的条件:

dp[i]=A(i)+B(j)中的最小/大值 (i-k<=j<i,k为常数)



例子:

dp[i]=dp[j]+(i-j)*w // 选自hdu3401

A(i)=i*w

B(j)=dp[j]-j*w



分析:

维护B(j)的最大合法值进行转移即可



实现:

建立一层循环i=1~n

每次先用i-k更新单调队列队头位置,然后用单调队列中的最值点更新dp[i],最后将B(i)加入单调队列
struct dddl//单调队列
{
int q[maxn];
int p[maxn];
int h,t;
void clear(){h=1,t=0;}
void eliminate(int minp){while(p[h]<minp&&h<=t) h++;}
void insert(int pos,int val)
{
while(q[t]<=val&&h<=t) t--;
q[++t]=val;
p[t]=pos;
}
int top(){return q[h];}
}que;
int dp[maxn];
void dynamic_programming()//以取最大值为例
{
que.clear();
dp[0]=0;
que.insert(0,0);//预处理,具体函数值视情况而定
for(int i=1;i<=n;i++)
{
que.eliminate(i-k);
dp[i]=que.top()+A(i);
que.insert(i,B(i));
}
}


斜率优化DP



DP转移方程需要满足的条件:

dp[i]=-A(i)*B(j)+C(i)+D(j) 中的最小值,j<i,A(x),B(x)为增函数
dp[i]=-A(i)*B(j)+C(i)+D(j) 中的最大值,j<i,A(x)为减函数,B(x)为增函数



例子:

dp[i]=dp[j]+(s[i]-s[j])^2 /*此处指平方*/ +M // 选自HDU3507

A(i)=s[i]

B(j)=s[j]*2

C(i)=s[i]*s[i]+M

D(j)=s[j]*s[j]+dp[j]



分析:

以取最小值为例

当从j>k,j转移到i比从k转移到i更优时有

-A(i)*B(j)+C(i)+D(j)<-A(i)*B(k)+C(i)+D(k)

变形得[D(j)-D(k)]/[B(j)-B(k)]<A(i)

设g(j,k)=[D(j)-D(k)]/[B(j)-B(k)]

可以证明,对于a<b<c,若g(c,b)<g(b,a),b永远不可能作为转移的最优决策,因为当g(c,b)<A(i),c比b优,当g(b,a)>g(c,b)>A(i),a比b优,那么b点可以删除
把D(j)当作y,B(j)当作x,那么g(j,k)就是连接j,k两点的线段斜率,最后维护出的队列为一个下凸包,如下图


当转移到i时我们选择前面的斜率小于A(i)后面斜率大于A(i)的点转移,顺便把队头定义到这个位置。
设找到点j,这样可以保证对于任意k>j有g(k,j)>A(i),j更优;对于任意k<j有g(j,k)<A(i),j还是更优



实现:

我们需要维护一个队列,使得其中元素两两之间的斜率递增

因为A(i)单增,所以可以定期删除队头元素,每次转移从队头取然后将新的点加入队尾并维护斜率单增
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
long long dp[maxn];
int que[maxn];
long long ky(int a,int b)
{
return D(a)-D(b);
}
long long kx(int a,int b)
{
return B(a)-B(b);
}
void dynamic_programming()//以取最小值为例
{
dp[0]=0;//预处理,具体函数值视情况而定
que[++t]=0;
for(int i=1;i<=n;i++)
{
while(t>h&&ky(que[h+1],que[h])<=kx(que[h+1],que[h])*A[i]) h++;
//一定要写成相乘形式,否则会引起除以0,精度低等一系列问题
dp[i]=A(i)*B(que[h])+C(i)+D(que[h]);
while(t>h&&ky(i,que[t])*kx(que[t],que[t-1])<=ky(que[t],que[t-1])*kx(i,que[t])) t--;
que[++t]=i;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  DP OI