第一阶段复习——动态规划2

状态压缩动态规划

就是对状态做一个压缩,一般是用二进制表示,比如

P1896 [SCOI2005] 互不侵犯

每一行的状态一般来说要开好多维数组,然而一个二进制就搞定了。

预处理:首先 1<<n 范围枚举状态,筛选出合法状态,记录每一个合法状态的点数。

fi,j,k 表示前 i 行,放 j 个士兵,当前行的状态是 k 的方案数。初始化 f0,0,0=1

转移:

对于前i行,放j个士兵的情况,考虑转移。双重循环枚举状态,分别用a和b表示(a循环在外),用c记录a状态的士兵数。

进行判断:如果j不小于c;正对判断;错位判断(位运算的巧用)。如果都满足,则 fi,j,a=fi1,jc,b

具体见代码。

最后有一个技巧,多算一层,直接输出 fn+1,k,0 就可以,虽说并没有节省时间复杂度。

P1879 [USACO06NOV] Corn Fields G

和上一个问题的区别就在于约束条件,变成了十字形的,另外还加了一个贫瘠土地的限制。

判断条件:!(s[a] & s[b]) && (s[a] & g[i]) == s[a]

第一个的意义是水平判断,和上题一样;第二个是障碍判断,位运算巧用。

滚动数组的另一种操作方法,用与运算来维护,每次更新 i1 的位置就好。

P2704 [NOI2001] 炮兵阵地

十字形的约束扩大了一层。

fi,a,b 表示前i行,第i行是状态a,第i-1行是状态b的方案数。

判断:

image

但这里面有一些冗余,删除之后:(因为比较状态合法只需要a-b,a-c之间合法,b-c就合法;另外,b这一层在a的上一层,b肯定已经被算过合法状态了,所以转移一定不会出现不合地图的情况,所以不用判断b的地图合法性)

image

转移:

f[i&1][a][b]=max(f[i&1][a][b],f[(i1)&1][b][c]+num[s[a]])

将第一维压缩为两个位,与运算交替,可以通过此题。

一些习题

P2622 关灯问题II;PRZ;P3694 邦邦的大合唱站队;P3092 [USACO13NOV] No Change G;P5005 中国象棋 - 摆上马

关灯问题

这题是求一个最小步数类型的题。设计状态 f[state] 表示state状态的最少步数,然后跑bfs就可以。但是重点在于处理操作。发现一个操作序列用一个二进制好像是无法表示的,那么就开两个。opt1用来搞1->0,opt2用来搞0->1。

下一个状态的获取:t = (u | opt1[i]) & (~opt2[i])

详细解释:

这个位运算操作可以做到将操作序列O(n)处理降到O(1)。但这个思路很nb。

首先考察这个操作的意义,对于一个操作序列:其中的1表示把当前状态u中对应位置的1变成0;-1表示把当前状态u中对应位置的0变成1;0表示无影响。

首先-1的意义可以想到或运算:将u和opt1[i]进行按位或,因为或运算只有在序列位置为1,u位置为0的时候起作用,因为序列中只有需要更改的地方是1,其余地方都是0,无影响!所以考虑需要更改的地方,正好。之后再考虑1操作,将1变成0,用~opt2[i]和u进行与运算,注意这个opt序列中也只有需要更改的信息,其他都是0,但是与运算的性质是1不变性,0必变性,所以要取反,这里1变为0,0仍然是0。

动态规划5】状态压缩动态规划

[能力提升综合题单Part4 动态规划2]

区间dp

石子合并

重点在于如何识别出来这道题是动态规划,即快速证伪贪心。因为只能取相邻两堆的限制,导致不能做到每次取到最小和。

破环成链复制一倍。

对于f[l][r]表示l~r的最小代价,g可以设为最大代价,这里我们只考虑f的转移,g同理。

对于区间dp的常见方法就是外层枚举跨度,内层枚举左端点,最内层枚举中间点。

那我们考虑f可以由中间点怎么转移得来。

f[l][r]=min(f[l][k]+f[k][r]+s[r]s[l1])

合并的代价是每次都有的,直接前缀和就好了。

最后枚举答案需要i从1~n枚举,然后跨度为n去选,因为复制了一倍。

能量项链

这题一样

有一个极简的写法:

for(int len = 3; len <= n + 1; len++)
        for(int i = 1, j; (j=i+len-1) <= 2 * n; i++)
            for(int k = i + 1 ;k < j; k++)
                f[i][j] = max(f[i][j], f[i][k] + f[k][j] + a[i] * a[k] * a[j]);

习题

P4290 [HAOI2008] 玩具取名;两道棋盘分割。

洛谷题单:【动态规划3】区间与环形动态规划

括号序列!

[HAOI2008] 玩具取名

这道题上来就想区间dp,然而实现的时候用的map和set,复杂了,tle半天。其实这个合并判断的处理用一个三维小数组就足够了。

本质就是区间dp,状态转移数组是 f[l][r][k], 还是布尔型的。

注意字符串从0开始,改成字符数组可以实现从1开始。

数位dp

三道例题

数字游戏1;数字游戏2;windy数。

练习

AHOI同类分布;手机号码

参考OIwiki的解说和习题。hm的ppt。

习题

usaco:P7415 P9129 P6006 P3607,这几道是guide上的,题解也在上面。

posted @   Vegdie  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示