qbzt培训整理系列之dp

此系列并木有按照顺序来,前面的有时间补上
跟我读:咕咕咕

--------这里是手动分割线----------

DP做题步骤

区间DP

经典题之能量项链
变环为链,然后搞正常的区间(dp)
不过还有一种做法是设(dp[i][len])表示从(i)往后推(len)个位置这一段合并的最大值
但本质都是一样的

感觉难一点的矩阵取数游戏

我们发现行与行之间的取数是互不影响的,也就是说每一行可以独立处理
辣么我们就独立处理每一行的最大得分,最后相加就可以了
(f[i][j])表示当前行被取的只剩下([i,j])的时候的最大得分
(f[i][j])可以由(f[i-1][j])(f[i][j+1])转移而来,而且取走(i-1)或者是取走(j+1)时乘的数是固定的,为(2^{m-j+i+1})
( herefore f[i][j]=max{f[i-1][j]+2^{m-j+i+1} imes a[i-1],f[i][j+1]+2^{m-j+i+1} imes a[j+1]})
(f[1][m])初始化为0,最大的(f[i][i]+a[i] imes 2^m)加入答案

背包好题

飞扬的小鸟

(f[i][j])表示在点((i,j))需要的最少点击次数
我们考虑是怎么到达当前位置的:
1.在上一列点了一下飞进来的
2.在本列点了若干下飞上来的
3.上一列不点,掉下来的
其中2的情况也可以认为是在上一列点了若干下,飞上来的。在转移的时候我们可以看做是先飞到((i,j-x[i-1])),再飞到((i,j))
因为往上飞的次数是无限的,所以我们可以视作完全背包,而往下掉只能有一次,所以往下掉就是01背包
往上飞:(f[i][j]=min{f[i-1][j-x[i-1]],f[i][j-x[i-1]]})
处理在((i,m))的情况:(f[i][m]=min{f[i][j]},jin [m-x[i-1],m])
往下掉:(f[i][j]=min{f[i][j],f[i-1][j+y[i-1]})
一些细节:被水管挡住的位置要在转移完之后赋值为正无穷表示不可到达

匹配dp

其实最长公共子序列就是个匹配(dp)
子串

这里选出的子串虽然不可以重叠,但是它们可以相邻
比如选出一串子串(abb)你可以说这是3个子串,也可以说是2个子串,还可以说是1个子串
我们模仿最长公共子序列,设(f[i][j])表示(A)的前(i)位和(B)的前(j)位匹配的方案数
似乎少了点什么.........
好像把(k)给忘了
如果考虑选出的子串个数,就要考虑(A)的第(i)位是否选
那么设(f[i][j][k][0/1])表示(A)的前(i)位中选出(k)个子串,其中第(i)位是/否在第(k)个子串中,与(B)的前(j)位匹配的方案数
考虑转移
(A[i+1]!=B[j+1])
反正(A[i+1])是不能塞进第(k)个子串里了,那么(f[i+1][j][k][0]+=f[i][j][k][0]+f[i][j][k][1])
(A[i+1]==B[j+1])
(A[i+1]):塞进第(k)个子串或者是新建一个子串:
(f[i+1][j+1][k][1]+=f[i][j][k][1])
(f[i+1][j+1][k+1][1]+=f[i][j][k][1]+f[i][j][k][0])
不选(A[i+1]):
与不相等的情况相同,(f[i+1][j][k][0]+=f[i][j][k][0]+f[i][j][k][1])

然后我们计算一下复杂度
时间复杂度:(O(nmk)),能苟住
空间复杂度:(8 imes 10^7)
噫好空间炸了
于是我们把(i)这一维用滚动数组滚掉

一些我不会分类的dp

货币系统

看到这题,我们可以先来一波直(xia)觉(cai)推测:

(b)应该是(a)的子集叭
而且(b)里面的元素应该是(a)中不能被除它自己以外的其他元素表达出来的元素,换句话说,就是把(a)能被重复表达的元素删掉

那么咱的直(xia)觉(cai)到底对不对呢
证一下叭
如果(b)中某一元素(x)不在(a)中:
如果(x)不能被(a)中的元素表达,则会(x)可表达(a)不能表达的新元素,不合题意
如果(x)可以被(a)中的元素表达,那么表达(x)的元素一定比(x)小,这些元素可以组合出(x)所不能表达的更多元素,所以还是不合题意
( herefore b)(a)的子集
如果(b)中有可以被重复表达的元素,那么删掉之后(m)会更小,所以(b)(a)把所有能被重复表达的元素删掉之后的集合

辣么我们就可以(dp)看看哪些元素会被重复表达了
(f[i]=0/1)表示面值(i)能否被小于它的面值表达出
初始化:(f[0]=1),其余为0
(a)数组从小到大排序,第一层枚举(a[i]),第二层枚举(x),(f[x+a[i]]|=f[x])

树网的核
(即消防弱化版)

然鹅数据被毒瘤地加到了1e6
也就是说消防的(nlogn)的做法也被卡掉了
真·毒瘤

这里直径上的每个点可以将树分成若干个以直径上的点为根的子树,这样就可以预处理出每个点分得的子树的最长距离(树形dp即可)
那么直径上每个点的点权可视作这个点分得的子树的最长距离
我们要求的是选中的路径上的点的点权+两侧距离的最大值最小
如果他不卡(nlogn)我们还可以二分对不对
但是他卡了
我们发现某个点到两侧的距离似乎可以(O(1))
而且根据直(xia)觉(cai),核的长度肯定是越接近(s)越优
辣么就是不断维护长度为(s)(或者接近(s))的路径上的最大值,看看最小是多少
因为长度固定,所以我们可以单调队列解决

to be continued

原文地址:https://www.cnblogs.com/lcez56jsy/p/13550866.html