window.cnblogsConfig = { homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

DP优化技巧

感谢https://www.luogu.com.cn/user/249973#main老师。

DP优化技巧

矩阵优化DP

1.矩阵快速幂(优化dp)

2.四边形不等式优化dp(a,b,c,d)(ac+bd<=ad+bc)

3.数据结构优化dp(线段树)

4.单调队列、二分栈优化dp

5.斜率优化dp

矩阵定义

矩阵乘法(更常见),矩阵加法

矩阵加法

一般式:Ci,j=Ai,j+Bi,j

其中A,B 均为NM 矩阵,矩阵A+B 得到NM 矩阵C

式子的含义为:矩阵C是由A,B对应位置上数值相加得到

注意:矩阵加法满足交换律

矩阵乘法

一般式:Ci,j=k=1K(Ai,kBk,j) ,其中ANK 的矩阵,BKM的矩阵,矩阵AB得到NM的矩阵C

式子的含义为:矩阵Ci,j由矩阵Ai行上的第K个数与矩阵B上的第j列上的第K个数分别相乘并求和得到

注意:矩阵乘法不满足交换律,满足结合律,满足分配率

前缀和优化dp

当转移遇到fi=l<=j<=rgj ,就可以对gj做一个前缀和,之后两端点差分

求和式可以转换成min,max

two-pointer优化dp

最常见的形式是“尺取法”。大概就是一个指针移动时,取最优值的另一个端点是单调移动的

我想在一个有序数组a中找到两个数ai,aj(i<j),使得ajai<=Cajai最大

当我们移动左端点i时,我们只需要找到aj<=C+ai的最大值即可,因为数组是有序的,所以j可以单调移动

本质就是固定一端点,最优化地移动另一个端点

这样我们就能省去其中一维的枚举,达到优化的目的

决策单调性对一类 1D/1D DP的优化

这里的xD/yD Dp的含义,是指的状态数由nx种,每个状态的转移有ny种的DP,而1D/1D Dp通常长这样

fi=min(fj+w(i,j))

而决策单调性是指,对于两个决策点j,k(j<k),如果对于状态i,决策k优于j,那么对于任意的i>i,都有决策点k优于j,即从k转移一定更优,j一定不会再成为最优决策,决策是单调的,跟双指针优化dp类似的

根据w(i,j)的不同性质,我们可以采取不同的优化方法

w(i,j)只包含i和j的项->单调队列优化

不妨将转移写成fi=min(max)(fj+a[i]+b[j]) 以min为例

因为ai和j无关,所以实际转移式fi=ai+min(max)(fj+b[j]) ,所以我们只需要找到括号里最小的就可以

如果ij<=K,那我们可以维护一个单调队列,储存的元素fj+b[j],当前假设我们枚举到i,这时候我们将要淘汰的元素就是j>=iK,(老且弱),我们只需要判断单调队列队首元素的下标,把不合法的情况删去即可,删去不合法的元素后,当前的队首就是合法的最小值,更新fi即可

w(i,j)只含有i,j和ij的项->斜率优化

不妨将转移写成fi=min(max)(a[i]b[j]+c[i]+d[j]) ,式中不含fj是因为fj可能参与了b[j]和d[j]的运算,隐去方便讨论且不影响后续结果,还是以min为例

现在需要的就是对于每个i,找到最优决策点j.对于每个i,只和j有关的是变量.于是我们将原式变形

d[j]=a[i]b[j]+c[i]f[i]

我们可以用线性规划来解决这个问题.用一次函数y=kx+b来描述这个过程.那么y=d[j],x=b[j],k=a[i],b=c[i]f[i]

现在我们需要fi尽可能的小,显然我们就是需要b=c[i]f[i]尽可能的大.于是我们对于[1,i1]之间的所有的j,把(b[j],d[j])刻画在坐标轴上,再用y=a[i]x+b去做线性规划

显然需要截距最大时,直线一定切于这些点的上凸包上,所以我们只需要维护一个上凸包即可

而如何在i不断枚举时,在不断有新的点加入的情况下去维护这一个上凸包呢?之前提出问题的时候已经说明了,b[j]是单调递增的,也就是说当我的循环变量往右枚举时,新增的点总会出现在所有之前的点的右边.所以我们可以开一个单调队列去一次存下凸包上的所有的点,单调队列中相邻两点斜率是单调递减的.所以如果出现如图所示的情况,那么就把队尾的点删掉,因为它不可能成为决策最优点.

删除之后重复这个过程,直到不出现这个情况

如图

而即使维护了这个上凸包,若还是利用遍历上凸包上的点来寻找最优决策点的话依旧是不可以的.如果我们能保证a[i]是单调递减,于是我们需要决策单调性优化,如果说i的最优决策点是j,那么显然任意取i>=i,i'的最优决策点k一定满足k>=j

并且对于最优决策点,记它和之前的一个点的斜率为k1,它和之后的一个决策点是k2,需要满足k1>a[i]>k2 ,因此每当作决策前,我们先判断队首和次队首的斜率是否大于a[i] ,如果是,队首出队,直到队首和次队首的连线斜率小于a[i],自此队首元素就是对于i的最优决策点

综上,每个点都最多只会进出队列一次,复杂度O(n)

回到最初的问题,究竟哪些性质的a,b可以用决策单调性的斜率优化,并且原因是什么呢?下面将给出一个更为普适的定理

决策单调性适用的定理--四边形不等式与决策单调性

在解释斜率优化那部分的遗留问题之前,我们需要对决策单调性这一整部分进行归纳总结

四边形不等式:对于任意的a<=b<=c<=d,有w(a,d)+w(b,c)>=w(a,c)+w(b,d)

四边形不等式并不等同于代数形式的不等式,它只是一些w的二元函数具备的特殊性质

定理:若w(i,j)满足四边形不等式,那1D/1D DP是可以用决策单调性优化的.

证明:

以优化的第一类式子为例,即fi=min(fj+w(i,j)) ,并且w满足w(a,d)+w(b,c)>=w(a,c)+w(b,d)

pi表示i的最优决策点是pi,那么有

fpi+w(pi,i)<=fj+w(j,i) (1)

同时,我们需要证明的式子是

fpi+1+w(pi+1,i+1)<=fj+w(j,i+1)(2)

把(2)式中的j变成pi

fpi+1+w(pi+1,i+1)<=fpi+w(pi,i+1)(3)

分情况讨论

1.pi+1=i,那么显然pi+1=i>=pi,满足决策单调性

2.pi+1!=i ,那么把(1)式中的j变成pi+1

fpi+w(pi,i)<=fpi+1+w(pi+1,i)(4)

(3)+(4)得

w(pi+1,i+1)+w(pi,i)<=w(pi,i+1)+w(pi+1,i)

如果pi>pi+1,代入上式,不等号和我们已知的不等号相反,显然矛盾.因此pi<=pi+1<=i<=i+1

综上pi<=pi+1,即满足决策单调性

模板

#include<bits/stdc++.h> #define int long long using namespace std; const int mod = 1e9+7; int n,k; struct matrix{ int a[105][105]; matrix operator*(const matrix & b) const {//重载乘法符号 matrix ret; for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ for(int k = 1;k <= n;k++){ ret.a[i][j] = (ret.a[i][j]+(a[i][k]*b.a[k][j]%mod)) % mod; } } } return ret; } matrix operator+(const matrix &b) const{//重载加法符号 matrix ret; for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ ret.a[i][j] = (a[i][j] + b.a[i][j]) % mod; } } return ret; } matrix(){ memset(a,0,sizeof a); } }; matrix qpow(matrix a,int x){//矩阵快速幂 matrix ret; for(int i = 1;i <= n;i++) ret.a[i][i] = 1; while(x){ if(x & 1) ret=ret*a; a=a*a; x>>=1; } return ret; } int k2; signed main(){ cin >> n >> k2; matrix a; for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ scanf("%lld",&a.a[i][j]); } } a=qpow(a,k2); for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ printf("%lld ",a.a[i][j]); } puts(""); } return 0; }

__EOF__

本文作者gsczl71
本文链接https://www.cnblogs.com/gsczl71/p/17854558.html
关于博主:GDSZ初一蒟蒻,明年拿下七级勾
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   gsczl71  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示