DP刷题记录

\(DP\)太菜了,开个随笔稍微记录一下

关路灯

挺经典一题

\(f[l][r][0/1]\)表示关掉\([l,r]\)内的路灯后在左侧还是右侧

然后转移方程

\(f[l][r][0]=min(f[l+1][r][0]+d[l][l+1]*(s[n]-s[r]+s[l]),f[l+1][r][1]+d[l][r]*(s[n]-s[r]+s[l]))\)

\(f[l][r][1]=min(f[l][r-1][0]+d[l][r]*(s[n]-s[r-1]+s[l-1]),f[l][r-1][1]+d[r-1][r]*(s[n]-s[r-1]+s[l-1]))\)

打砖块

不能直接背包,因为不知道最后一个\(Y\)到底有没有子弹

预处理\(v[i][j][0/1]\)表示第\(i\)列用\(j\)发子弹,最后一发打在\(N/Y\)

也就是说遇到一个\(N\)上面是\(Y\)的情况,可以把上面的\(Y\)压缩到下面的\(N\)上,用\(1\)来表示

如果不是这种情况就把\(v[i][j][0]\)\(v[i][j][1]\)一起用\(v[i][j-1][1]\)更新

设计\(f[i][j][0/1]\)表示前\(i\)列用\(j\)发,最后一发是\(N/Y\)的最大值

然后就可以了,如果枚举哪一列,一共用了几发,这一列用几发

转移要注意的有点多:

\(1.f[i][j][1]=max(f[i-1][j-k][1]+v[i][k][1])\)

表示如果一直有子弹可以借从别的地方借一个打掉最上面的\(Y\)再还回去的最大值

\(2.if(k) f[i][j][0]=max(f[i-1][j-k][1]+v[i][k][0])\)

这个表示从当前列借一发子弹给前面的列,得到的最大结果

\(3.if(j>k) f[i][j][0]=max(f[i-1][j-k][0]+v[i][k][1])\)

这个表示从前面的某一列借一发给当前列,得到的最大结果

答案是\(max(f[m][j][0])\)

迎接仪式

\(f[i][j][k][0/1]\)表示到\(i\)位置,有\(j\)\(0\)变成\(1\),有\(k\)\(1\)变成\(0\),结尾是\(0/1\)

然后就……\(ning\)转移,最后取\(max\{f[n][i][i][0/1]\}\)

时态同步

就……求出最长的,然后树上模拟??

然后……数组忘了调大+\(sb\)错误\(WA\)了两发

低价购买

这都能蓝?黄的差不多

问最长严格下降子序列长度,和数值不同的最长严格下降子序列个数

第一问\(O(n^2)dp\),第二问我们发现,只要边\(dp\)边记录次数,然后往前更新答案的时候遇到同样的数字就\(break\)就行了

道路游戏

\(s[i][k]\)表示在\(i\)时刻\(k\)这个位置的前缀和,注意每个时刻机器人位置都变化所以这个前缀和是错位的……

然后就可以得到\(O(n^3)\)\(dp\)方程:\(f[i]=max\{f[i-k]+s[i][j]-s[i-k][(j-k+p*n)\%n]-w[(j-k+p*n)\%n]\}\)

其中\(i\)是时间,\(j\)是当前位置,\(k\)是设定的移动距离

然后卡过了

为了有脸还是优化一下

然后我们变形一下方程得到 \(f[i]=max\{f[i-k]-s[i-k][(j-k+p*n)\%n]-w[(j-k+p*n)\%n]\}+s[i][j]\)

那单调队列维护一下前面这个\(max\)里的东西就好了

写起来稍微有点麻烦

统计单词个数

先求出\(f[l][r]\)表示\([l,r]\)内能分出多少个单词,只要枚举\(r\)然后倒推\(l\)就可以\(O(n^2)\)实现

然后\(dp[i][k]\)表示到\(i\)分了\(k\)段的最大答案,注意\(k<=i\)

你可能感兴趣的:(DP刷题记录)