首页 > 其他分享 >DP优化技巧

DP优化技巧

时间:2023-11-24 19:11:38浏览次数:39  
标签:技巧 dp min 矩阵 决策 单调 优化 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

矩阵定义

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

矩阵加法

一般式:\(C_{i,j}=A_{i,j}+B_{i,j}\)

其中\(A,B\) 均为\(N*M\) 矩阵,矩阵\(A+B\) 得到\(N*M\) 矩阵\(C\)

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

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

矩阵乘法

一般式:\(C_{i,j}=\sum\limits_{k=1}^K (A_{i,k}*B_{k,j})\) ,其中\(A\)为\(N*K\) 的矩阵,\(B\)为\(K*M\)的矩阵,矩阵\(A*B\)得到\(N*M\)的矩阵\(C\)

式子的含义为:矩阵\(C_{i,j}\)由矩阵\(A\)第\(i\)行上的第\(K\)个数与矩阵\(B\)上的第\(j\)列上的第\(K\)个数分别相乘并求和得到

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

前缀和优化dp

当转移遇到\(f_i = \sum_\limits{l<=j<=r}g_j\) ,就可以对\(g_j\)做一个前缀和,之后两端点差分

求和式可以转换成\(min,max\)

two-pointer优化dp

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

我想在一个有序数组\(a\)中找到两个数\(a_i,a_j(i<j)\),使得\(a_j-a_i<=C\)且\(a_j-a_i\)最大

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

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

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

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

这里的xD/yD Dp的含义,是指的状态数由\(n^x\)种,每个状态的转移有\(n^y\)种的DP,而1D/1D Dp通常长这样

\[f_i=min(f_j+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的项->单调队列优化

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

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

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

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

不妨将转移写成\(f_i=min(max)(a[i]*b[j]+c[i]+d[j])\) ,式中不含\(f_j\)是因为\(f_j\)可能参与了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]\)

现在我们需要\(f_i\)尽可能的小,显然我们就是需要\(b=c[i]-f[i]\)尽可能的大.于是我们对于\([1,i-1]\)之间的所有的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,需要满足\(k_1>a[i]>k_2\) ,因此每当作决策前,我们先判断队首和次队首的斜率是否大于\(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是可以用决策单调性优化的.

证明:

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

设\(p_i\)表示i的最优决策点是\(p_i\),那么有

\(f_{p_i}+w(p_i,i)<=f_j+w(j,i)\) (1)

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

\(f_{p_{i+1}}+w(p_{i+1},i+1)<=f_j+w(j,i+1)\)(2)

把(2)式中的j变成\(p_i\)

\(f_{p_{i+1}}+w(p_{i+1},i+1)<=f_{p_i}+w(p_i,i+1)\)(3)

分情况讨论

1.\(p_{i+1}=i\),那么显然\(p_{i+1}=i>=p_i\),满足决策单调性

2.\(p_{i+1}!=i\) ,那么把(1)式中的j变成\(p_{i+1}\)

\(f_{p_i}+w(p_i,i)<=f_{p_{i+1}}+w(p_{i+1},i)\)(4)

(3)+(4)得

\(w(p_{i+1},i+1)+w(p_i,i)<=w(p_i,i+1)+w(p_{i+1},i)\)

如果\(p_i>p_{i+1}\),代入上式,不等号和我们已知的不等号相反,显然矛盾.因此\(p_i<=p_{i+1}<=i<=i+1\)

综上\(p_i<=p_{i+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;
}

标签:技巧,dp,min,矩阵,决策,单调,优化,DP
From: https://www.cnblogs.com/gsczl71/p/17854558.html

相关文章

  • Android IntentService的开发技巧
    Android应用开发中,执行后台任务是常见需求之一。其中,IntentService是一种强大的工具,可以轻松管理异步任务,而无需担心线程管理和生命周期问题。本文将深入探讨IntentService的各个方面,包括基本用法、特点、生命周期、与其他服务的比较以及最佳实践等内容。引言在移动应用开发中,......
  • [ABC321G] Electric Circuit 状压DP
    用到了好多技巧的状压DP我们先统计总数然后除以m的阶乘就可以了设f[i]表示状态为i的集合造成的贡献数(也就是状态为i的集合不与集合外的点联通且这个集合联通块数是1的情况数)不与集合外的点联通的话只用考虑结合i之间连边,集合外那些点之间两边就可以啦这个集合联通块数是1......
  • 后端的性能优化有哪些方面?
    Java的性能优化可以从多个方面入手,从影响性能的方面考虑一下。包括以下几个方面:线程池调优:适当地调整线程池的大小和线程数,可以提高程序的并发性能和响应速度。内存管理:合理地管理内存使用,包括对象的创建和销毁,可以提高程序的执行效率。IO操作优化:采用NIO方式可以减少IO......
  • (Python)基于对称点模式(Symmetrized Dot Pattern,SDP)的多元、多通道、多传感器信号融合
    对称点模式(SymmetrizedDotPattern,SDP)算法可将复杂时间序列以散点的形式清晰映射在极坐标图中,可以使原始时域信号通过图形化的方式提高可视化能力。因为极坐标图像的特殊性,多元、多通道、多传感器信号信息可通过SDP方法融合在有限区域中。适用于多元、多通道、多传感器信号的融合......
  • colab 使用技巧
    无法进入目录importospath="/content/TaBERT/"os.chdir(path)print(os.getcwd())无法执行conda!pipinstall-qcondacolabimportcondacolabcondacolab.install()......
  • blender布线优化
    在雕刻模式下选中滑动松弛(拓补)笔刷进行使用:该笔刷将网格的拓扑滑移到细节更多的区域,同时尽可能少地改变网格的集合形状。当按下Shift键时,该笔刷进入平滑模式该模式下笔刷将在不改变网格的体积的情况下使四边面的分布更平均。编辑模式下按A全选点然后按M选择按距离合并......
  • ThreadPoolTaskExecutor类
    ThreadPoolTaskExecutor类可用来创建线程池并添加任务1TreadPoolTaskExecutortaskExecutor=newThreadPoolTaskExecutor();2taskExecutor.setCorePoolSize(5);//设置核心线程数3taskExecutor.setMaxPollSize(10);//设置最大线程数4taskExecutor.setQu......
  • 一文掌握MySQL多表查询技巧:告别繁琐操作,轻松搞定数据查询!
    在数据库的世界里,我们经常需要处理各种各样的数据。有时候,我们需要从多个表中查询数据,这时候就需要用到MySQL的多表查询了。今天,就让我们一起来了解一下MySQL多表查询的魅力吧!一、表的关系简介现实生活中,实体与实体之间肯定是有关系的,比如:部门和员工,老师和学生等。在设计表的时......
  • 2023华为杯研究生赛awdp-web复现
    被我们web队组会狠狠push了...但是看了下这个研究生赛的题目,难度还是不高的,还不至于队里佬们打实时比赛我看着都费劲那种...........
  • mysql 一些优化参数
     大批量数据加载优化load数据加载格式:loaddatalocalinfile'文件路径'intotable表名fieldsterminatedby'[分隔符]'lineterminatedby'[换行符]'11、首先,检测全局变量‘local_infile’的状态,如果是off状态则是不可用showglobalvariableslike'local_infile';......