Bootstrap

DP(动态规划)进阶

  • 一些非典型的动态规划串讲:
  • 状态压缩进阶
  • 期望概率进阶
  • 数位DP
  • 换根DP
  • 基环树DP
  • 主要是介绍思想,要提升必须靠练习

状态压缩 

什么是状态压缩呢

当一道题的状态很复杂,但是很少的时候,我们考虑暴力的状态表示出来

绝大部分状压 DP 压缩的都是二进制,用来表示某些东西取/没取 这样的状态。

指数级复杂度,适用于数据范围较小的题目

通常会出现在棋盘问题中:

比如说:[SCOI2005]互不侵犯[NOI2001]炮兵阵地

有的时候还要考虑如何优化减小状态数

二进制的使用

查找第k位:(S>>k)&1

将第k位置为1S|=(1<<k)

将第k位置为0S&=~(1<<k)

枚举子集:for(i=S;i&=S;--i);

求二进制位上1的个数:for(r=0;x;++r,x&=(x-1));

大概就这些,然后左移右移都是可以子集脑补的

例题A:[NOI2001]炮兵阵地

 

https://www.luogu.org/problemnew/show/P2704

n*m的地上,有些格子是山地,有些格子是平原,可以在平原上部署部队,一个部队的攻击范围是沿横向左右各两格,沿纵向上下各两格。在互不侵犯的情况下,问最大的部署部队数 n≤100 ,?≤10n≤100 ,m≤10

状压dp基础题?根据

????表示一行状态L,当前?行的状态?最大答案f[L][S][i]表示上一行的状态是L,当前第i行的状态是S的最大答案

每次枚举????−1+??????更新????f[P][S][i-1]+count(S)来更新f[L][S][i]其中count?其中count(S)表示S中包含1的个数,考虑如何满足题设的条件:

左右的关系:  S&S<<1=0 S&S<<2=0

上下的关系:S&L=0,S&P=0[bzoj 4197][Noi 2015]寿司晚宴

[SDOI2009]学校食堂

https://www.luogu.org/problemnew/show/P2157

N个人,每人有个口味T和忍耐度B(允许排在他之后的前B个人在他之前打饭),必须给每个人做他口味的菜,做每道菜的时间是(last or now-last and now),一开始last=0,最小化时间。?≤1000??≤7n≤1000,B_i≤7

f???表示?−1个人打完菜,包括?在内之后7个人打饭状态?f[i][S][l]表示前i-1个人打完菜,包括i在内的之后7个人打饭状态为S

上一个打菜的是?−7i-7位开始的第?个,花费最少时间的第l个,花费的最少时间0?≤150≤l≤15

用刷表法

如果S&1==0,也就是第i个人已经打过饭,则直接用它更新f?+1?≫1?−1更新f[i+1][S≫1][l-1]

否则,枚举还没取到的位k,更新f??|(1≪?)?即可f[i][S|(1≪k)][k]即可

当然还要注意判断当前没打饭的人当然还要注意判断当前没打饭的人是否都满足忍耐度限制

[bzoj 4197][Noi 2015]寿司晚宴

 

题意

2~n中选出两个集合AB,满足集合A的数均与集合B的数互质,询问方案数,选出的集合可以为空。

?≤500n≤500

题解

首先,集合AB不相交,可以看成是用到的质因数集合不同

;